new mlx4 Tx datapath bypassing ibverbs
cover new mlx4 Tx datapath bypassing ibverbs
This series of patches implements the mlx4-pmd with Tx data path that directly access the device queues for transmitting packets, bypassing the ibverbs Tx data path altogether.
Using this scheme allows the PMD to work with upstream rdma-core package instead of the Mellanox OFED one without sacrificing Tx functionality.
These patches should be applied in the order listed below as each depends on its predecessor to work.
This implementation allows rapid deployment of new features without the need to update the underlying OFED.
This work depends on
http://dpdk.org/ml/archives/dev/2017-August/072281.html
[dpdk-dev] [PATCH v1 00/48] net/mlx4: trim and refactor entire PMD
by Adrien Mazarguil
It had been built and tested using rdma-core-15-1 from
https://github.com/linux-rdma/rdma-core
and kernel-ml-4.12.0-1.el7.elrepo.x86_64
It had been built and tested using rdma-core-15-1 from
https://github.com/linux-rdma/rdma-core
and kernel-ml-4.12.0-1.el7.elrepo.x86_64
Moti Haimovsky (5):
net/mlx4: add simple Tx bypassing ibverbs
net/mlx4: support multi-segments Tx
net/mlx4: refine setting Tx completion flag
net/mlx4: add Tx checksum offloads
net/mlx4: add loopback Tx from VF
drivers/net/mlx4/mlx4.c | 7 + drivers/net/mlx4/mlx4.h | 2 + drivers/net/mlx4/mlx4_ethdev.c | 6 + drivers/net/mlx4/mlx4_prm.h | 249 ++++++++++++++++++++++ drivers/net/mlx4/mlx4_rxtx.c | 456 +++++++++++++++++++++++++++++++++-------- drivers/net/mlx4/mlx4_rxtx.h | 39 +++- drivers/net/mlx4/mlx4_txq.c | 66 +++++- mk/rte.app.mk | 2 +- 8 files changed, 734 insertions(+), 93 deletions(-) create mode 100644 drivers/net/mlx4/mlx4_prm.h
Signature · 1 line
1.8.3.1
PATCH 1/5 net/mlx4: add simple Tx bypassing ibverbs
PMD now sends the single-buffer packets directly to the device bypassing the ibv Tx post and poll routines.
--- drivers/net/mlx4/mlx4_prm.h | 253 +++++++++++++++++++++++++++++++++++++++++ drivers/net/mlx4/mlx4_rxtx.c | 260 +++++++++++++++++++++++++++++++++++-------- drivers/net/mlx4/mlx4_rxtx.h | 30 ++++- drivers/net/mlx4/mlx4_txq.c | 52 ++++++++- mk/rte.app.mk | 2 +- 5 files changed, 546 insertions(+), 51 deletions(-) create mode 100644 drivers/net/mlx4/mlx4_prm.h
drivers/net/mlx4/mlx4_prm.h new file +253 -0
@@ -0,0 +1,253 @@ +/*- +* BSD LICENSE +* +* Copyright 2017 Mellanox. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of 6WIND S.A. nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef RTE_PMD_MLX4_MLX4_PRM_H_ +#define RTE_PMD_MLX4_MLX4_PRM_H_ + +/* Verbs headers do not support -pedantic. */ +#ifdef PEDANTIC +#pragma GCC diagnostic ignored "-Wpedantic" +#endif +#include <infiniband/verbs.h> +#include <infiniband/mlx4dv.h> +#ifdef PEDANTIC +#pragma GCC diagnostic error "-Wpedantic" +#endif + +/* Basic TxQ building block */ +#define TXBB_SHIFT 6 +#define TXBB_SIZE (1 << TXBB_SHIFT) + +/* Typical TSO descriptor with 16 gather entries is 352 bytes... */ +#define MAX_WQE_SIZE 512 +#define MAX_WQE_TXBBS (MAX_WQE_SIZE / TXBB_SIZE) + +/* Send Queue Stamping/Invalidating info */ +#define SQ_STAMP_STRIDE 64 +#define SQ_STAMP_DWORDS (SQ_STAMP_STRIDE / 4) +#define SQ_STAMP_SHIFT 31 +#define SQ_STAMP_VAL 0x7fffffff + +/* WQE flags */ +#define MLX4_OPCODE_SEND 0x0a +#define MLX4_EN_BIT_WQE_OWN 0x80000000 + +#define SIZE_TO_TXBBS (size) (RTE_ALIGN((size), (TXBB_SIZE)) / (TXBB_SIZE)) + +/** +* Update the HW with the new CQ consumer value. +* +* @param cq +* Pointer to the cq structure. +*/ +static inline void +mlx4_cq_set_ci (struct mlx4_cq *cq) +{ + *cq->set_ci_db =rte_cpu_to_be_32 (cq->cons_index &0xffffff ); +} + +/** +* Returns a pointer to the cqe in position n. +* +* @param cq +* Pointer to the cq structure. +* @param n +* The number of the entry its address we seek. +* +* @return +* pointer to the cqe. +*/ +static inline struct mlx4_cqe +*mlx4_get_cqe (struct mlx4_cq *cq,int n) +{ +return (struct mlx4_cqe *)(cq->buf + n * cq->cqe_size); +} + +/** +* Returns a pointer to the cqe in position n if it is owned by SW. +* +* @param cq +* Pointer to the cq structure. +* @param n +* The number of the entry its address we seek. +* +* @return +* pointer to the cqe if owned by SW, otherwise returns NULL. +*/ +static inline void +*mlx4_get_sw_cqe (struct mlx4_cq *cq,int n) +{ +struct mlx4_cqe *cqe =mlx4_get_cqe (cq, n & (cq->cqe_cnt -1 )); +struct mlx4_cqe *tcqe = cq->cqe_size ==64 ? cqe +1 : cqe; + +return (!!(tcqe->owner_sr_opcode &MLX4_CQE_OWNER_MASK ) ^ + !!(n & cq->cqe_cnt)) ?NULL : cqe; +} + +/** +* returns pointer to the wqe at position n. +* +* @param sq +* Pointer to the sq. +* @param n +* The entry number the queue. +* +* @return +* A pointer to the required entry. +*/ +static inline void +*mlx4_get_send_wqe (struct mlx4_sq *sq,unsigned int n) +{ +return sq->buf + n *TXBB_SIZE ; +} + +/** +* returns the size in bytes of this WQE. +* +* @param wqe +* Pointer to the WQE we want to interrogate. +* +* @return +* WQE size in bytes. +*/ +static inline int +mlx4_wqe_get_real_size (void *wqe) +{ +struct mlx4_wqe_ctrl_seg *ctrl = (struct mlx4_wqe_ctrl_seg *)wqe; +return ((ctrl->fence_size &0x3f ) <<4 ); +} + +/** +* Fills the ctrl segment of a WQE with info needed for transmitting the packet. +* +* @param seg +* Pointer to the control structure in the WQE. +* @param owner +* The value for the owner field. +* @param fence_size +* Fence bit and WQE size in octowords. +* @param srcrb_flags +* High 24 bits are SRC remote buffer; low 8 bits are flags. +* @param imm +* Immediate data/Invalidation key.. +*/ +static inline void +mlx4_set_ctrl_seg (struct mlx4_wqe_ctrl_seg *seg,uint32_t owner, +uint8_t fence_size,uint32_t srcrb_flags,uint32_t imm) +{ + seg->fence_size = fence_size; + seg->srcrb_flags =rte_cpu_to_be_32 (srcrb_flags); +/* +* The caller should prepare "imm" in advance based on WR opcode. +* For IBV_WR_SEND_WITH_IMM and IBV_WR_RDMA_WRITE_WITH_IMM, +* the "imm" should be assigned as is. +* For the IBV_WR_SEND_WITH_INV, it should be htobe32(imm). +*/ + seg->imm = imm; +/* +* Make sure descriptor is fully written before +* setting ownership bit (because HW can start +* executing as soon as we do). +*/ +rte_wmb (); + seg->owner_opcode =rte_cpu_to_be_32 (owner); +} + +/** +* Fills a data segment of a WQE with info needed for transmitting +* a data fragment. +* +* @param dseg +* Pointer to a data segment structure in the WQE. +* (WQE may contain several data segments). +* @param sq +* fragment info (addr, length, lkey). +*/ +static inline void +mlx4_set_data_seg (struct mlx4_wqe_data_seg *dseg,struct ibv_sge *sg) +{ + dseg->lkey =rte_cpu_to_be_32 (sg->lkey); + dseg->addr =rte_cpu_to_be_64 (sg->addr); + +/* +* Need a barrier here before writing the byte_count field to +* make sure that all the data is visible before the +* byte_count field is set. Otherwise, if the segment begins +* a new cacheline, the HCA prefetcher could grab the 64-byte +* chunk and get a valid (!= * 0xffffffff) byte count but +* stale data, and end up sending the wrong data. +*/ +rte_io_wmb (); + +if (likely (sg->length)) + dseg->byte_count =rte_cpu_to_be_32 (sg->length); +else +/* Zero len seg is treated as inline segment with zero data */ + dseg->byte_count =rte_cpu_to_be_32 (0x80000000 ); +} + +/** +* Checks if a BBE sized WQE can be inserted to the sq without +* overflowing the Q and that theWQE is not over-sized. +* +* @param sq +* Pointer to the sq we want to put the wqe in. +* @param ntxbb +* Number of EBBs the WQE occupies. +*/ +static inline int +mlx4_wq_overflow (struct mlx4_sq *sq,int ntxbb) +{ +unsigned int cur; + + cur = sq->head - sq->tail; +return ((cur + ntxbb + sq->headroom_txbbs >= sq->txbb_cnt) || + (ntxbb >MAX_WQE_TXBBS )); +} + +/** +* Calc the WQE size (in bytes) needed for posting this packet. +* +* @param count +* The number of data-segments the WQE contains. +* +* @return +* WQE size in bytes. +*/ +static inline int +mlx4_wqe_calc_real_size (unsigned int count) +{ +return sizeof (struct mlx4_wqe_ctrl_seg ) + + (count *sizeof (struct mlx4_wqe_data_seg )); +} + +#endif /* RTE_PMD_MLX4_MLX4_PRM_H_ */
drivers/net/mlx4/mlx4_rxtx.c +213 -47
326 lines not on this page · raw message
drivers/net/mlx4/mlx4_rxtx.h +29 -1
@@ -41,6 +41,7 @@#pragma GCC diagnostic ignored "-Wpedantic"#endif #include <infiniband/verbs.h> +#include <infiniband/mlx4dv.h> #ifdef PEDANTIC #pragma GCC diagnostic error "-Wpedantic"#endif
@@ -90,7 +91,7 @@ struct txq_elt {struct rte_mbuf *buf;/**< Buffer. */ }; -/** Rx queue counters. */ +/** Tx queue counters. */ struct mlx4_txq_stats {unsigned int idx;/**< Mapping index. */ uint64_t opackets;/**< Total of successfully sent packets. */
@@ -98,6 +99,31 @@ struct mlx4_txq_stats {uint64_t odropped;/**< Total of packets not sent when Tx ring full. */ }; +/** TXQ Info */ +struct mlx4_sq { +char *buf;/**< SQ buffer. */ +uint32_t size;/**< SQ size in bytes. */ +uint32_t head;/**< SQ head counter in units of TXBBS. */ +uint32_t tail;/**< SQ tail counter in units of TXBBS. */ +uint32_t txbb_cnt;/**< Num of WQEBB in the Q (should be ^2). */ +uint32_t txbb_shift;/**< The log2 size of the basic block. */ +uint32_t txbb_cnt_mask;/**< txbbs_cnt mask (txbb_cnt is ^2). */ +uint32_t headroom_txbbs;/**< Num of txbbs that should be kept free .*/ +uint32_t *db;/**< Pointer to the doorbell. */ +uint32_t doorbell_qpn;/**< qp number to write to the doorbell. */ +}; + +struct mlx4_cq { +char *buf;/**< CQ buffer. */ +uint32_t size;/**< CQ size in bytes. */ +uint32_t cqe_cnt;/**< Num of entries the CQ has. */ +int cqe_size;/**< size (in bytes) of a CQE. */ +uint32_t *set_ci_db;/**< Pionter of the consumer-index doorbell. */ +uint32_t cons_index;/**< last CQE entry that was handled. */ +uint32_t factor;/**< CQ data location in a CQE. */ +int cqn;/**< CQ number */ +}; +/** Tx queue descriptor. */ struct txq {struct priv *priv;/**< Back pointer to private data. */
@@ -118,6 +144,8 @@ struct txq {unsigned int elts_comp_cd_init;/**< Initial value for countdown. */ struct mlx4_txq_stats stats;/**< Tx queue counters. */ unsigned int socket;/**< CPU socket ID for allocations. */ +struct mlx4_sq msq;/**< Info for directly manipulating the SQ. */ +struct mlx4_cq mcq;/**< Info for directly manipulating the CQ. */ };/* mlx4_rxq.c */
drivers/net/mlx4/mlx4_txq.c +50 -2
88 lines not on this page · raw message
mk/rte.app.mk +1 -1
@@ -128,7 +128,7 @@ ifeq ($(CONFIG_RTE_LIBRTE_KNI),y) _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_KNI) += -lrte_pmd_kni endif _LDLIBS-$(CONFIG_RTE_LIBRTE_LIO_PMD) += -lrte_pmd_lio -_LDLIBS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += -lrte_pmd_mlx4 -libverbs +_LDLIBS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += -lrte_pmd_mlx4 -libverbs -lmlx4 _LDLIBS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += -lrte_pmd_mlx5 -libverbs _LDLIBS-$(CONFIG_RTE_LIBRTE_NFP_PMD) += -lrte_pmd_nfp _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += -lrte_pmd_null
Signature · 1 line
1.8.3.1
PATCH 2/5 net/mlx4: support multi-segments Tx
In reply to Moti HaimovskyPRM now supports transmitting packets spanning over arbitrary amount of buffers.
--- drivers/net/mlx4/mlx4_prm.h | 16 +--- drivers/net/mlx4/mlx4_rxtx.c | 213 +++++++++++++++++++++++++++++++------------ drivers/net/mlx4/mlx4_rxtx.h | 3 +- drivers/net/mlx4/mlx4_txq.c | 12 ++- 4 files changed, 170 insertions(+), 74 deletions(-)
drivers/net/mlx4/mlx4_prm.h +5 -11
@@ -61,7 +61,7 @@#define MLX4_OPCODE_SEND 0x0a#define MLX4_EN_BIT_WQE_OWN 0x80000000 -#define SIZE_TO_TXBBS (size) (RTE_ALIGN((size), (TXBB_SIZE)) / (TXBB_SIZE)) +#define SIZE_TO_TXBBS (size) (RTE_ALIGN((size), (TXBB_SIZE)) / (TXBB_SIZE))/** * Update the HW with the new CQ consumer value.
@@ -148,6 +148,7 @@/** * Fills the ctrl segment of a WQE with info needed for transmitting the packet. +* Owner field is filled later. * * @param seg * Pointer to the control structure in the WQE.
@@ -161,8 +162,8 @@* Immediate data/Invalidation key.. */ static inline void -mlx4_set_ctrl_seg (struct mlx4_wqe_ctrl_seg *seg,uint32_t owner, -uint8_t fence_size,uint32_t srcrb_flags,uint32_t imm) +mlx4_set_ctrl_seg (struct mlx4_wqe_ctrl_seg *seg,uint8_t fence_size, +uint32_t srcrb_flags,uint32_t imm) { seg->fence_size = fence_size; seg->srcrb_flags =rte_cpu_to_be_32 (srcrb_flags);
@@ -173,13 +174,6 @@* For the IBV_WR_SEND_WITH_INV, it should be htobe32(imm). */ seg->imm = imm; -/* -* Make sure descriptor is fully written before -* setting ownership bit (because HW can start -* executing as soon as we do). -*/ -rte_wmb (); - seg->owner_opcode =rte_cpu_to_be_32 (owner); }/**
@@ -241,7 +235,7 @@* The number of data-segments the WQE contains. * * @return -* WQE size in bytes. +* The calculated WQE size in bytes. */ static inline int mlx4_wqe_calc_real_size (unsigned int count)
drivers/net/mlx4/mlx4_rxtx.c +153 -60
264 lines not on this page · raw message
drivers/net/mlx4/mlx4_rxtx.h +2 -1
@@ -139,13 +139,14 @@ struct txq {struct txq_elt (*elts)[];/**< Tx elements. */ unsigned int elts_head;/**< Current index in (*elts)[]. */ unsigned int elts_tail;/**< First element awaiting completion. */ -unsigned int elts_comp;/**< Number of completion requests. */ +unsigned int elts_comp;/**< Number of pkts waiting for completion. */ unsigned int elts_comp_cd;/**< Countdown for next completion. */ unsigned int elts_comp_cd_init;/**< Initial value for countdown. */ struct mlx4_txq_stats stats;/**< Tx queue counters. */ unsigned int socket;/**< CPU socket ID for allocations. */ struct mlx4_sq msq;/**< Info for directly manipulating the SQ. */ struct mlx4_cq mcq;/**< Info for directly manipulating the CQ. */ +char *bounce_buf;/**< Side memory to be used when wqe wraps around */ };/* mlx4_rxq.c */
drivers/net/mlx4/mlx4_txq.c +10 -2
@@ -83,8 +83,14 @@rte_calloc_socket ("TXQ" ,1 ,sizeof (*elts),0 , txq->socket);int ret =0 ; -if (elts ==NULL ) { -ERROR ("%p: can't allocate packets array" , (void *)txq); +/* Allocate Bounce-buf memory */ + txq->bounce_buf = (char *)rte_zmalloc_socket ("TXQ" , +MAX_WQE_SIZE , +RTE_CACHE_LINE_MIN_SIZE , + txq->socket); + +if ((elts ==NULL ) || (txq->bounce_buf ==NULL )) { +ERROR ("%p: can't allocate TXQ memory" , (void *)txq); ret =ENOMEM ; goto error; }
@@ -110,6 +116,8 @@assert (ret ==0 );return 0 ; error: +if (txq->bounce_buf !=NULL ) +rte_free (txq->bounce_buf);if (elts !=NULL )rte_free (elts);DEBUG ("%p: failed, freed everything" , (void *)txq);
Signature · 1 line
1.8.3.1
PATCH 3/5 net/mlx4: refine setting Tx completion flag
In reply to Moti HaimovskyPMD now take into consideration the amount of entries in the TxQ a packet occupies when choosing weather to set the report-completion flag to the chip or not.
--- drivers/net/mlx4/mlx4_rxtx.c | 30 +++++++++++------------------- drivers/net/mlx4/mlx4_rxtx.h | 2 +- 2 files changed, 12 insertions(+), 20 deletions(-)
drivers/net/mlx4/mlx4_rxtx.c +11 -19
@@ -461,14 +461,16 @@/* Fill-in date from last to first */ for (i = wr->num_sge -1 ; i >=0 ; --i)mlx4_set_data_seg (dseg + i, wr->sg_list + i); -/* Handle control info -* -* For raw eth, the SOLICIT flag is used to indicate that -* no icrc should be calculated -*/ - srcrb_flags =MLX4_WQE_CTRL_SOLICIT | - ((wr->send_flags &IBV_SEND_SIGNALED ) ? -MLX4_WQE_CTRL_CQ_UPDATE :0 ); +/* Handle control info */ +/* For raw eth always set the SOLICIT flag */ +/* Request Tx completion. */ + txq->elts_comp_cd -= nr_txbbs; +if (unlikely (txq->elts_comp_cd <=0 )) { + srcrb_flags =MLX4_WQE_CTRL_SOLICIT |MLX4_WQE_CTRL_CQ_UPDATE ; + txq->elts_comp_cd = txq->elts_comp_cd_init; + }else { + srcrb_flags =MLX4_WQE_CTRL_SOLICIT ; + } fence_size = (wr->send_flags &IBV_SEND_FENCE ?MLX4_WQE_CTRL_FENCE :0 ) | ((wqe_real_size /16 ) &0x3f ); owner_opcode = MLX4_OPCODE_SEND |
@@ -514,13 +516,12 @@struct ibv_send_wr *wr_bad =NULL ;unsigned int elts_head = txq->elts_head;const unsigned int elts_n = txq->elts_n; -unsigned int elts_comp_cd = txq->elts_comp_cd;unsigned int elts_comp =0 ;unsigned int i;unsigned int max;int err; -assert (elts_comp_cd !=0 ); +assert (txq->elts_comp_cd !=0 );mlx4_txq_complete (txq); max = (elts_n - (elts_head - txq->elts_tail));if (max > elts_n)
@@ -560,11 +561,6 @@ tmp = next; }while (tmp !=NULL ); } -/* Request Tx completion. */ -if (unlikely (--elts_comp_cd ==0 )) { - elts_comp_cd = txq->elts_comp_cd_init; - send_flags |=IBV_SEND_SIGNALED ; - }if (buf->pkt_len <= txq->max_inline) send_flags |=IBV_SEND_INLINE ;/* Update element. */
@@ -580,9 +576,6 @@/* post the pkt for sending */ err =mlx4_post_send (txq, buf, wr, &wr_bad);if (unlikely (err)) { -if (unlikely (wr_bad->send_flags & -IBV_SEND_SIGNALED )) - elts_comp_cd =1 ; elt->buf =NULL ; goto stop; }
@@ -602,7 +595,6 @@mlx4_send_flush (txq); txq->elts_head = elts_head; txq->elts_comp += elts_comp; - txq->elts_comp_cd = elts_comp_cd;return i; }
drivers/net/mlx4/mlx4_rxtx.h +1 -1
@@ -140,7 +140,7 @@ struct txq {unsigned int elts_head;/**< Current index in (*elts)[]. */ unsigned int elts_tail;/**< First element awaiting completion. */ unsigned int elts_comp;/**< Number of pkts waiting for completion. */ -unsigned int elts_comp_cd;/**< Countdown for next completion. */ +int elts_comp_cd;/**< Countdown for next completion. */ unsigned int elts_comp_cd_init;/**< Initial value for countdown. */ struct mlx4_txq_stats stats;/**< Tx queue counters. */ unsigned int socket;/**< CPU socket ID for allocations. */
Signature · 1 line
1.8.3.1
PATCH 4/5 net/mlx4: add Tx checksum offloads
In reply to Moti HaimovskyPMD now supports offloading the ip and tcp/udp checksum header calculation (including tunneled packets) to the hardware.
--- drivers/net/mlx4/mlx4.c | 7 +++++++ drivers/net/mlx4/mlx4.h | 2 ++ drivers/net/mlx4/mlx4_ethdev.c | 6 ++++++ drivers/net/mlx4/mlx4_prm.h | 2 ++ drivers/net/mlx4/mlx4_rxtx.c | 25 +++++++++++++++++++++---- drivers/net/mlx4/mlx4_rxtx.h | 2 ++ drivers/net/mlx4/mlx4_txq.c | 4 +++- 7 files changed, 43 insertions(+), 5 deletions(-)
drivers/net/mlx4/mlx4.c +7 -0
@@ -397,6 +397,7 @@ struct mlx4_conf { .ports.present = 0, };unsigned int vf; +unsigned int tunnel_en;int i; (void )pci_drv;
@@ -456,6 +457,9 @@ struct mlx4_conf { rte_errno =ENODEV ; goto error; } +/* Only cx3-pro supports L3 tunneling */ + tunnel_en = (device_attr.vendor_part_id == +PCI_DEVICE_ID_MELLANOX_CONNECTX3PRO );INFO ("%u port(s) detected" , device_attr.phys_port_cnt); conf.ports.present |= (UINT64_C (1 ) << device_attr.phys_port_cnt) -1 ;if (mlx4_args (pci_dev->device.devargs, &conf)) {
@@ -529,6 +533,9 @@ struct mlx4_conf { priv->pd = pd; priv->mtu =ETHER_MTU ; priv->vf = vf; + priv->tunnel_en = tunnel_en; + priv->hw_csum = + !!(device_attr.device_cap_flags &IBV_DEVICE_RAW_IP_CSUM );/* Configure the first MAC address by default. */ if (mlx4_get_mac (priv, &mac.addr_bytes)) { ERROR("cannot get MAC address, is mlx4_en loaded?"
drivers/net/mlx4/mlx4.h +2 -0
@@ -104,6 +104,8 @@ struct priv { unsigned int vf:1; /* This is a VF device. */ unsigned int intr_alarm:1; /* An interrupt alarm is scheduled. */ unsigned int isolated:1; /* Toggle isolated mode. */ + unsigned int hw_csum:1; /* Checksum offload is supported. */ + unsigned int tunnel_en:1; /* Device tunneling is enabled */struct rte_intr_handle intr_handle;/* Port interrupt handle. */ struct rte_flow_drop *flow_drop_queue;/* Flow drop queue. */ LIST_HEAD(mlx4_flows, rte_flow) flows;
drivers/net/mlx4/mlx4_ethdev.c +6 -0
@@ -553,6 +553,12 @@ info->max_mac_addrs =1 ; info->rx_offload_capa =0 ; info->tx_offload_capa =0 ; +if (priv->hw_csum) + info->tx_offload_capa |= (DEV_TX_OFFLOAD_IPV4_CKSUM | +DEV_TX_OFFLOAD_UDP_CKSUM | +DEV_TX_OFFLOAD_TCP_CKSUM ); +if (priv->tunnel_en) + info->tx_offload_capa |=DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM ;if (mlx4_get_ifname (priv, &ifname) ==0 ) info->if_index =if_nametoindex (ifname); info->speed_capa =
drivers/net/mlx4/mlx4_prm.h +2 -0
@@ -60,6 +60,8 @@/* WQE flags */ #define MLX4_OPCODE_SEND 0x0a#define MLX4_EN_BIT_WQE_OWN 0x80000000 +#define MLX4_WQE_CTRL_IIP_HDR_CSUM (1 << 28) +#define MLX4_WQE_CTRL_IL4_HDR_CSUM (1 << 27)#define SIZE_TO_TXBBS (size) (RTE_ALIGN((size), (TXBB_SIZE)) / (TXBB_SIZE))
drivers/net/mlx4/mlx4_rxtx.c +21 -4
@@ -475,9 +475,27 @@ MLX4_WQE_CTRL_FENCE : 0) | ((wqe_real_size / 16) & 0x3f); owner_opcode =MLX4_OPCODE_SEND | ((sq->head & sq->txbb_cnt) ?MLX4_EN_BIT_WQE_OWN :0 ); +/* Should we enable HW CKSUM offload ? */ +if (txq->priv->hw_csum && + (pkt->ol_flags & + (PKT_TX_IP_CKSUM |PKT_TX_TCP_CKSUM |PKT_TX_UDP_CKSUM ))) { +const uint64_t is_tunneled = pkt->ol_flags & + (PKT_TX_TUNNEL_GRE | +PKT_TX_TUNNEL_VXLAN ); + +if (is_tunneled && txq->tunnel_en) { + owner_opcode |=MLX4_WQE_CTRL_IIP_HDR_CSUM | +MLX4_WQE_CTRL_IL4_HDR_CSUM ; +if (pkt->ol_flags &PKT_TX_OUTER_IP_CKSUM ) + srcrb_flags |=MLX4_WQE_CTRL_IP_HDR_CSUM ; + }else { + srcrb_flags |=MLX4_WQE_CTRL_IP_HDR_CSUM | +MLX4_WQE_CTRL_TCP_UDP_CSUM ; + } + }/* fill in ctrl info but ownership */ mlx4_set_ctrl_seg (ctrl, fence_size, srcrb_flags,0 ); -/* If we used a bounce buffer then copy wqe back into sq */ +/* If we used a bounce buffer then copy wqe back into sq */ if (unlikely (bounce)) ctrl =mlx4_bounce_to_desc (txq, head_idx, wqe_size);/*
@@ -485,9 +503,8 @@* setting ownership bit (because HW can start * executing as soon as we do). */ -rte_wmb (); - ctrl->owner_opcode =rte_cpu_to_be_32 (owner_opcode); - +rte_wmb (); + ctrl->owner_opcode =rte_cpu_to_be_32 (owner_opcode); sq->head += nr_txbbs;rte_wmb ();return 0 ;
drivers/net/mlx4/mlx4_rxtx.h +2 -0
@@ -146,6 +146,8 @@ struct txq {unsigned int socket;/**< CPU socket ID for allocations. */ struct mlx4_sq msq;/**< Info for directly manipulating the SQ. */ struct mlx4_cq mcq;/**< Info for directly manipulating the CQ. */ + uint16_t tunnel_en:1; +/* When set TX offload for tunneled packets are supported. */ char *bounce_buf;/**< Side memory to be used when wqe wraps around */ };
drivers/net/mlx4/mlx4_txq.c +3 -1
@@ -306,7 +306,7 @@ struct txq_mp2mr_mbuf_check_data {struct mlx4dv_obj mlxdv;struct mlx4dv_qp dv_qp;struct mlx4dv_cq dv_cq; -struct txq tmpl = { +struct txq tmpl = { .priv = priv, .socket = socket };
@@ -334,6 +334,8 @@ struct txq_mp2mr_mbuf_check_data { (void *)dev, strerror(rte_errno)); goto error; } +if (priv->tunnel_en) + tmpl.tunnel_en =1 ;DEBUG ("priv->device_attr.max_qp_wr is %d" , priv->device_attr.max_qp_wr); DEBUG("priv->device_attr.max_sge is %d",
Signature · 1 line
1.8.3.1
PATCH 5/5 net/mlx4: add loopback Tx from VF
In reply to Moti HaimovskyAdded loopback functionality use when the chip is a VF in order to enable packet transmission between VFs and between VFs and PF.
--- drivers/net/mlx4/mlx4_prm.h | 2 +- drivers/net/mlx4/mlx4_rxtx.c | 28 ++++++++++++++++++++++------ drivers/net/mlx4/mlx4_rxtx.h | 2 ++ drivers/net/mlx4/mlx4_txq.c | 2 ++ 4 files changed, 27 insertions(+), 7 deletions(-)
drivers/net/mlx4/mlx4_prm.h +1 -1
@@ -168,7 +168,7 @@ uint32_t srcrb_flags, uint32_t imm) { seg->fence_size = fence_size; - seg->srcrb_flags =rte_cpu_to_be_32 (srcrb_flags); + seg->srcrb_flags = srcrb_flags;/* * The caller should prepare "imm" in advance based on WR opcode. * For IBV_WR_SEND_WITH_IMM and IBV_WR_RDMA_WRITE_WITH_IMM,
drivers/net/mlx4/mlx4_rxtx.c +22 -6
@@ -426,7 +426,11 @@struct mlx4_wqe_data_seg *dseg;struct mlx4_sq *sq = &txq->msq;struct ibv_sge sge[wr->num_sge]; -uint32_t srcrb_flags; +union { +uint32_t flags; +uint16_t flags16[2 ]; + } srcrb; +uint32_t imm =0 ;uint8_t fence_size;uint32_t head_idx = sq->head & sq->txbb_cnt_mask;uint32_t owner_opcode;
@@ -466,10 +470,10 @@/* Request Tx completion. */ txq->elts_comp_cd -= nr_txbbs;if (unlikely (txq->elts_comp_cd <=0 )) { - srcrb_flags =MLX4_WQE_CTRL_SOLICIT |MLX4_WQE_CTRL_CQ_UPDATE ; + srcrb.flags =MLX4_WQE_CTRL_SOLICIT |MLX4_WQE_CTRL_CQ_UPDATE ; txq->elts_comp_cd = txq->elts_comp_cd_init; }else { - srcrb_flags =MLX4_WQE_CTRL_SOLICIT ; + srcrb.flags =MLX4_WQE_CTRL_SOLICIT ; } fence_size = (wr->send_flags &IBV_SEND_FENCE ?MLX4_WQE_CTRL_FENCE :0 ) | ((wqe_real_size /16 ) &0x3f );
@@ -487,14 +491,26 @@ owner_opcode |=MLX4_WQE_CTRL_IIP_HDR_CSUM |MLX4_WQE_CTRL_IL4_HDR_CSUM ;if (pkt->ol_flags &PKT_TX_OUTER_IP_CKSUM ) - srcrb_flags |=MLX4_WQE_CTRL_IP_HDR_CSUM ; + srcrb.flags |=MLX4_WQE_CTRL_IP_HDR_CSUM ; }else { - srcrb_flags |=MLX4_WQE_CTRL_IP_HDR_CSUM | + srcrb.flags |=MLX4_WQE_CTRL_IP_HDR_CSUM |MLX4_WQE_CTRL_TCP_UDP_CSUM ; } } +/* convert flags to BE before adding the mac address (if at all) +* to it +*/ + srcrb.flags =rte_cpu_to_be_32 (srcrb.flags); +/* Copy dst mac address to wqe. This allows loopback in eSwitch, +* so that VFs and PF can communicate with each other +*/ +if (txq->lb) { + srcrb.flags16[0] = *(rte_pktmbuf_mtod(pkt, uint16_t *)); + imm = *(rte_pktmbuf_mtod_offset (pkt ,uint32_t *, + sizeof(uint16_t))); + }/* fill in ctrl info but ownership */ -mlx4_set_ctrl_seg (ctrl, fence_size, srcrb_flags,0 ); +mlx4_set_ctrl_seg (ctrl, fence_size, srcrb.flags, imm);/* If we used a bounce buffer then copy wqe back into sq */ if (unlikely (bounce)) ctrl =mlx4_bounce_to_desc (txq, head_idx, wqe_size);
drivers/net/mlx4/mlx4_rxtx.h +2 -0
@@ -148,6 +148,8 @@ struct txq {struct mlx4_cq mcq;/**< Info for directly manipulating the CQ. */ uint16_t tunnel_en:1;/* When set TX offload for tunneled packets are supported. */ + uint16_t lb:1; +/* Whether pkts should be looped-back by eswitch or not */ char *bounce_buf;/**< Side memory to be used when wqe wraps around */ };
drivers/net/mlx4/mlx4_txq.c +2 -0
@@ -410,6 +410,8 @@ struct txq_mp2mr_mbuf_check_data { (void *)dev, strerror(rte_errno)); goto error; } +/* If a VF device - need to loopback xmitted packets */ + tmpl.lb = !!(priv->vf);/* Clean up txq in case we're reinitializing it. */ DEBUG ("%p: cleaning-up old txq just in case" , (void *)txq);mlx4_txq_cleanup (txq);
Signature · 1 line
1.8.3.1
v2 cover new mlx4 datapath bypassing ibverbs
In reply to Moti Haimovskyv2:
Rearange patches.
Semantics.
Enhancements.
Fix compilation issues.
Moti Haimovsky (6):
net/mlx4: add simple Tx bypassing ibverbs
net/mlx4: get back Rx flow functionality
net/mlx4: support multi-segments Tx
net/mlx4: get back Tx checksum offloads
net/mlx4: get back Rx checksum offloads
net/mlx4: add loopback Tx from VF
drivers/net/mlx4/mlx4.c | 11 + drivers/net/mlx4/mlx4.h | 13 +- drivers/net/mlx4/mlx4_ethdev.c | 10 + drivers/net/mlx4/mlx4_prm.h | 129 +++++++ drivers/net/mlx4/mlx4_rxq.c | 181 ++++++---- drivers/net/mlx4/mlx4_rxtx.c | 787 ++++++++++++++++++++++++++++++----------- drivers/net/mlx4/mlx4_rxtx.h | 61 ++-- drivers/net/mlx4/mlx4_txq.c | 104 +++++- drivers/net/mlx4/mlx4_utils.h | 20 ++ mk/rte.app.mk | 2 +- 10 files changed, 989 insertions(+), 329 deletions(-) create mode 100644 drivers/net/mlx4/mlx4_prm.h
Signature · 1 line
1.8.3.1
PATCH v2 1/6 net/mlx4: add simple Tx bypassing ibverbs
From: Moti Haimovsky <[email protected]>
Modify PMD to send single-buffer packets directly to the device bypassing the ibv Tx post and poll routines.
--- drivers/net/mlx4/mlx4_prm.h | 108 +++++++++++++ drivers/net/mlx4/mlx4_rxtx.c | 353 ++++++++++++++++++++++++++++++++----------- drivers/net/mlx4/mlx4_rxtx.h | 32 ++-- drivers/net/mlx4/mlx4_txq.c | 90 ++++++++--- mk/rte.app.mk | 2 +- 5 files changed, 463 insertions(+), 122 deletions(-) create mode 100644 drivers/net/mlx4/mlx4_prm.h
drivers/net/mlx4/mlx4_prm.h new file +108 -0
@@ -0,0 +1,108 @@ +/*- +* BSD LICENSE +* +* Copyright 2017 6WIND S.A. +* Copyright 2017 Mellanox +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of 6WIND S.A. nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef RTE_PMD_MLX4_PRM_H_ +#define RTE_PMD_MLX4_PRM_H_ + +#include <rte_byteorder.h> +#include <rte_branch_prediction.h> +#include <rte_atomic.h> + +/* Verbs headers do not support -pedantic. */ +#ifdef PEDANTIC +#pragma GCC diagnostic ignored "-Wpedantic" +#endif +#include <infiniband/verbs.h> +#include <infiniband/mlx4dv.h> +#ifdef PEDANTIC +#pragma GCC diagnostic error "-Wpedantic" +#endif + +/* ConnectX-3 Tx queue basic block. */ +#define MLX4_TXBB_SHIFT 6 +#define MLX4_TXBB_SIZE (1 << MLX4_TXBB_SHIFT) + +/* Typical TSO descriptor with 16 gather entries is 352 bytes. */ +#define MLX4_MAX_WQE_SIZE 512 +#define MLX4_MAX_WQE_TXBBS (MLX4_MAX_WQE_SIZE / MLX4_TXBB_SIZE) + +/* Send queue stamping/invalidating information. */ +#define MLX4_SQ_STAMP_STRIDE 64 +#define MLX4_SQ_STAMP_DWORDS (MLX4_SQ_STAMP_STRIDE / 4) +#define MLX4_SQ_STAMP_SHIFT 31 +#define MLX4_SQ_STAMP_VAL 0x7fffffff + +/* Work queue element (WQE) flags. */ +#define MLX4_BIT_WQE_OWN 0x80000000 + +#define MLX4_SIZE_TO_TXBBS (size) \ + (RTE_ALIGN((size), (MLX4_TXBB_SIZE)) >> (MLX4_TXBB_SHIFT)) + +/* Send queue information. */ +struct mlx4_sq { +char *buf;/**< SQ buffer. */ +char *eob;/**< End of SQ buffer */ +uint32_t head;/**< SQ head counter in units of TXBBS. */ +uint32_t tail;/**< SQ tail counter in units of TXBBS. */ +uint32_t txbb_cnt;/**< Num of WQEBB in the Q (should be ^2). */ +uint32_t txbb_cnt_mask;/**< txbbs_cnt mask (txbb_cnt is ^2). */ +uint32_t headroom_txbbs;/**< Num of txbbs that should be kept free. */ +uint32_t *db;/**< Pointer to the doorbell. */ +uint32_t doorbell_qpn;/**< qp number to write to the doorbell. */ +}; + +#define mlx4_get_send_wqe (sq, n) ((sq)->buf + ((n) * (MLX4_TXBB_SIZE))) + +/* Completion queue information. */ +struct mlx4_cq { +char *buf;/**< Pointer to the completion queue buffer. */ +uint32_t cqe_cnt;/**< Number of entries in the queue. */ +uint32_t cqe_64:1 ;/**< CQ entry size is 64 bytes. */ +uint32_t cons_index;/**< Last queue entry that was handled. */ +uint32_t *set_ci_db;/**< Pointer to the completion queue doorbell. */ +}; + +/* +* cqe = cq->buf + cons_index * cqe_size + cqe_offset +* Where cqe_size is 32 or 64 bytes and +* cqe_offset is 0 or 32 (depending on cqe_size). +*/ +#define mlx4_get_cqe (cq, n) (__extension__({ \ + typeof(cq) q = (cq); \ + (q)->buf + \ + (((n) & ((q)->cqe_cnt - 1)) << \ + (5 + (q)->cqe_64)) + \ + ((q)->cqe_64 << 5); \ + })) + +#endif /* RTE_PMD_MLX4_PRM_H_ */
drivers/net/mlx4/mlx4_rxtx.c +263 -90
445 lines not on this page · raw message
drivers/net/mlx4/mlx4_rxtx.h +18 -14
@@ -40,6 +40,7 @@#ifdef PEDANTIC #pragma GCC diagnostic ignored "-Wpedantic"#endif +#include <infiniband/mlx4dv.h> #include <infiniband/verbs.h> #ifdef PEDANTIC #pragma GCC diagnostic error "-Wpedantic"
@@ -50,6 +51,7 @@#include <rte_mempool.h> #include "mlx4.h" +#include "mlx4_prm.h" /** Rx queue counters. */ struct mlx4_rxq_stats {
@@ -85,8 +87,6 @@ struct rxq {/** Tx element. */ struct txq_elt { -struct ibv_send_wr wr;/* Work request. */ -struct ibv_sge sge;/* Scatter/gather element. */ struct rte_mbuf *buf;/**< Buffer. */ };
@@ -100,24 +100,28 @@ struct mlx4_txq_stats {/** Tx queue descriptor. */ struct txq { -struct priv *priv;/**< Back pointer to private data. */ -struct { -const struct rte_mempool *mp;/**< Cached memory pool. */ -struct ibv_mr *mr;/**< Memory region (for mp). */ -uint32_t lkey;/**< mr->lkey copy. */ - } mp2mr[MLX4_PMD_TX_MP_CACHE ];/**< MP to MR translation table. */ -struct ibv_cq *cq;/**< Completion queue. */ -struct ibv_qp *qp;/**< Queue pair. */ -uint32_t max_inline;/**< Max inline send size. */ -unsigned int elts_n;/**< (*elts)[] length. */ -struct txq_elt (*elts)[];/**< Tx elements. */ +struct mlx4_sq msq;/**< Info for directly manipulating the SQ. */ +struct mlx4_cq mcq;/**< Info for directly manipulating the CQ. */ unsigned int elts_head;/**< Current index in (*elts)[]. */ unsigned int elts_tail;/**< First element awaiting completion. */ unsigned int elts_comp;/**< Number of completion requests. */ unsigned int elts_comp_cd;/**< Countdown for next completion. */ unsigned int elts_comp_cd_init;/**< Initial value for countdown. */ +unsigned int elts_n;/**< (*elts)[] length. */ +struct txq_elt (*elts)[];/**< Tx elements. */ struct mlx4_txq_stats stats;/**< Tx queue counters. */ -unsigned int socket;/**< CPU socket ID for allocations. */ +uint32_t max_inline;/**< Max inline send size. */ +struct { +const struct rte_mempool *mp;/**< Cached memory pool. */ +struct ibv_mr *mr;/**< Memory region (for mp). */ +uint32_t lkey;/**< mr->lkey copy. */ + } mp2mr[MLX4_PMD_TX_MP_CACHE ];/**< MP to MR translation table. */ +struct { +struct priv *priv;/**< Back pointer to private data. */ +unsigned int socket;/**< CPU socket ID for allocations. */ +struct ibv_cq *cq;/**< Completion queue. */ +struct ibv_qp *qp;/**< Queue pair. */ + } ctrl; };/* mlx4_rxq.c */
drivers/net/mlx4/mlx4_txq.c +73 -17
170 lines not on this page · raw message
mk/rte.app.mk +1 -1
@@ -128,7 +128,7 @@ ifeq ($(CONFIG_RTE_LIBRTE_KNI),y) _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_KNI) += -lrte_pmd_kni endif _LDLIBS-$(CONFIG_RTE_LIBRTE_LIO_PMD) += -lrte_pmd_lio -_LDLIBS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += -lrte_pmd_mlx4 -libverbs +_LDLIBS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += -lrte_pmd_mlx4 -libverbs -lmlx4 _LDLIBS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += -lrte_pmd_mlx5 -libverbs _LDLIBS-$(CONFIG_RTE_LIBRTE_NFP_PMD) += -lrte_pmd_nfp _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += -lrte_pmd_null
Signature · 1 line
1.8.3.1
PATCH v2 2/6 net/mlx4: get back Rx flow functionality
In reply to Matan AzradFrom: Moti Haimovsky <[email protected]>
This patch adds support for accessing the hardware directly when handling Rx packets eliminating the need to use verbs in the Rx datapath.
Now the number of scatters is calculated on the fly, according to the maximum expected packet size.
--- drivers/net/mlx4/mlx4.h | 11 -- drivers/net/mlx4/mlx4_rxq.c | 176 +++++++++++++++++++------------- drivers/net/mlx4/mlx4_rxtx.c | 229 ++++++++++++++++++++++++------------------ drivers/net/mlx4/mlx4_rxtx.h | 19 ++-- drivers/net/mlx4/mlx4_utils.h | 20 ++++ 5 files changed, 268 insertions(+), 187 deletions(-)
drivers/net/mlx4/mlx4.h +0 -11
@@ -57,17 +57,6 @@/* Maximum size for inline data. */ #define MLX4_PMD_MAX_INLINE 0 -/* -* Maximum number of cached Memory Pools (MPs) per TX queue. Each RTE MP -* from which buffers are to be transmitted will have to be mapped by this -* driver to their own Memory Region (MR). This is a slow operation. -* -* This value is always 1 for RX queues. -*/ -#ifndef MLX4_PMD_TX_MP_CACHE -#define MLX4_PMD_TX_MP_CACHE 8 -#endif -/* Interrupt alarm timeout value in microseconds. */ #define MLX4_INTR_ALARM_TIMEOUT 100000
drivers/net/mlx4/mlx4_rxq.c +108 -68
291 lines not on this page · raw message
drivers/net/mlx4/mlx4_rxtx.c +131 -98
252 lines not on this page · raw message
drivers/net/mlx4/mlx4_rxtx.h +9 -10
@@ -62,13 +62,6 @@ struct mlx4_rxq_stats {uint64_t rx_nombuf;/**< Total of Rx mbuf allocation failures. */ }; -/** Rx element. */ -struct rxq_elt { -struct ibv_recv_wr wr;/**< Work request. */ -struct ibv_sge sge;/**< Scatter/gather element. */ -struct rte_mbuf *buf;/**< Buffer. */ -}; -/** Rx queue descriptor. */ struct rxq {struct priv *priv;/**< Back pointer to private data. */
@@ -78,9 +71,15 @@ struct rxq {struct ibv_qp *qp;/**< Queue pair. */ struct ibv_comp_channel *channel;/**< Rx completion channel. */ unsigned int port_id;/**< Port ID for incoming packets. */ -unsigned int elts_n;/**< (*elts)[] length. */ -unsigned int elts_head;/**< Current index in (*elts)[]. */ -struct rxq_elt (*elts)[];/**< Rx elements. */ +unsigned int elts_n;/**< Log 2 of Mbufs. */ +struct rte_mbuf *(*elts)[];/**< Rx elements. */ +struct { +volatile struct mlx4_wqe_data_seg (*wqes)[]; +volatile uint32_t *rq_db; +uint16_t rq_ci; + } hw; +struct mlx4_cq mcq;/**< Info for directly manipulating the CQ. */ +unsigned int sge_n;/**< Log 2 of SGEs number. */ struct mlx4_rxq_stats stats;/**< Rx queue counters. */ unsigned int socket;/**< CPU socket ID for allocations. */ };
drivers/net/mlx4/mlx4_utils.h +20 -0
@@ -108,4 +108,24 @@int mlx4_fd_set_non_blocking (int fd); +/** +* Return nearest power of two above input value. +* +* @param v +* Input value. +* +* @return +* Nearest power of two above input value. +*/ +static inline unsigned int +log2above (unsigned int v) +{ +unsigned int l; +unsigned int r; + +for (l =0 , r =0 ; (v >>1 ); ++l, v >>=1 ) + r |= (v &1 ); +return l + r; +} +#endif /* MLX4_UTILS_H_ */
Signature · 1 line
1.8.3.1
PATCH v2 3/6 net/mlx4: support multi-segments Tx
In reply to Matan AzradFrom: Moti Haimovsky <[email protected]>
This patch adds support for transmitting packets spanning over multiple buffers.
In this patch we also take into consideration the amount of entries a packet occupies in the TxQ when setting the report-completion flag of the chip.
--- drivers/net/mlx4/mlx4_rxtx.c | 208 ++++++++++++++++++++++++------------------- drivers/net/mlx4/mlx4_rxtx.h | 6 +- drivers/net/mlx4/mlx4_txq.c | 12 ++- 3 files changed, 129 insertions(+), 97 deletions(-)
drivers/net/mlx4/mlx4_rxtx.c +116 -92
@@ -63,6 +63,16 @@#include "mlx4_rxtx.h" #include "mlx4_utils.h" +/* +* Pointer-value pair structure +* used in tx_post_send for saving the first DWORD (32 byte) +* of a TXBB0 +*/ +struct pv { +struct mlx4_wqe_data_seg *dseg; +uint32_t val; +}; +/** * Stamp a WQE so it won't be reused by the HW. * Routine is used when freeing WQE used by the chip or when failing
@@ -296,34 +306,38 @@* * @param txq * The Tx queue to post to. -* @param wr -* The work request to handle. -* @param bad_wr -* The wr in case that posting had failed. +* @param pkt +* The packet to transmit. * * @return * 0 - success, negative errno value otherwise and rte_errno is set. */ static inline int mlx4_post_send (struct txq *txq, -struct rte_mbuf *pkt, -uint32_t send_flags) +struct rte_mbuf *pkt) {struct mlx4_wqe_ctrl_seg *ctrl;struct mlx4_wqe_data_seg *dseg;struct mlx4_sq *sq = &txq->msq; +struct rte_mbuf *buf;uint32_t head_idx = sq->head & sq->txbb_cnt_mask;uint32_t lkey;uintptr_t addr; +uint32_t srcrb_flags; +uint32_t owner_opcode =MLX4_OPCODE_SEND ; +uint32_t byte_count;int wqe_real_size;int nr_txbbs;int rc; +struct pv *pv = (struct pv *)txq->bounce_buf; +int pv_counter =0 ;/* Calculate the needed work queue entry size for this packet. */ wqe_real_size =sizeof (struct mlx4_wqe_ctrl_seg ) + pkt->nb_segs *sizeof (struct mlx4_wqe_data_seg ); nr_txbbs =MLX4_SIZE_TO_TXBBS (wqe_real_size); -/* Check that there is room for this WQE in the send queue and +/* +* Check that there is room for this WQE in the send queue and * that the WQE size is legal. */ if (likely(((sq->head - sq->tail) + nr_txbbs +
@@ -332,76 +346,108 @@ rc =ENOSPC ; goto err; } -/* Get the control and single-data entries of the WQE */ +/* Get the control and data entries of the WQE. */ ctrl = (struct mlx4_wqe_ctrl_seg *)mlx4_get_send_wqe (sq, head_idx); dseg = (struct mlx4_wqe_data_seg *)(((char *)ctrl) +sizeof (struct mlx4_wqe_ctrl_seg )); -/* -* Fill the data segment with buffer information. -*/ - addr =rte_pktmbuf_mtod (pkt, uintptr_t); -rte_prefetch0 ((volatile void *)addr); - dseg->addr =rte_cpu_to_be_64 (addr); -/* Memory region key for this memory pool. */ - lkey =mlx4_txq_mp2mr (txq,mlx4_txq_mb2mp (pkt)); -if (unlikely (lkey == (uint32_t )-1 )) { -/* MR does not exist. */ -DEBUG ("%p: unable to get MP <-> MR" -" association" , (void *)txq); -/* -* Restamp entry in case of failure. -* Make sure that size is written correctly. -* Note that we give ownership to the SW, not the HW. +/* Fill the data segments with buffer information. */ +for (buf = pkt; buf !=NULL ; buf = buf->next, dseg++) { + addr =rte_pktmbuf_mtod (buf, uintptr_t); +rte_prefetch0 ((volatile void *)addr); +/* Handle WQE wraparound. */ +if (unlikely (dseg >= (struct mlx4_wqe_data_seg *)sq->eob)) + dseg = (struct mlx4_wqe_data_seg *)sq->buf; + dseg->addr =rte_cpu_to_be_64 (addr); +/* Memory region key for this memory pool. */ + lkey =mlx4_txq_mp2mr (txq,mlx4_txq_mb2mp (buf)); +if (unlikely (lkey == (uint32_t )-1 )) { +/* MR does not exist. */ +DEBUG ("%p: unable to get MP <-> MR" +" association" , (void *)txq); +/* +* Restamp entry in case of failure. +* Make sure that size is written correctly +* Note that we give ownership to the SW, not the HW. +*/ + ctrl->fence_size = (wqe_real_size >>4 ) &0x3f ; +mlx4_txq_stamp_freed_wqe (sq, head_idx, + (sq->head & sq->txbb_cnt) ?0 :1 ); + rc =EFAULT ; + goto err; + } + dseg->lkey =rte_cpu_to_be_32 (lkey); +if (likely (buf->data_len)) + byte_count =rte_cpu_to_be_32 (buf->data_len); +else +/* +* Zero length segment is treated as inline segment +* with zero data. +*/ + byte_count =RTE_BE32 (0x80000000 ); +/* If the data segment is not at the beginning of a +* Tx basic block(TXBB) then write the byte count, +* else postpone the writing to just before updating the +* control segment. */ - ctrl->fence_size = (wqe_real_size >>4 ) &0x3f ; -mlx4_txq_stamp_freed_wqe (sq, head_idx, - (sq->head & sq->txbb_cnt) ?0 :1 ); - rc =EFAULT ; - goto err; +if ((uintptr_t )dseg & (uintptr_t )(MLX4_TXBB_SIZE -1 )) { +/* +* Need a barrier here before writing the byte_count +* fields to make sure that all the data is visible +* before the byte_count field is set. +* Otherwise, if the segment begins a new cacheline, +* the HCA prefetcher could grab the 64-byte chunk and +* get a valid (!= * 0xffffffff) byte count but stale +* data, and end up sending the wrong data. +*/ +rte_io_wmb (); + dseg->byte_count = byte_count; + }else { +/* +* This data segment starts at the beginning of a new +* TXBB, so we need to postpone its byte_count writing +* for later. +*/ + pv[pv_counter].dseg = dseg; + pv[pv_counter++].val = byte_count; + } } - dseg->lkey =rte_cpu_to_be_32 (lkey); -/* -* Need a barrier here before writing the byte_count field to -* make sure that all the data is visible before the -* byte_count field is set. Otherwise, if the segment begins -* a new cacheline, the HCA prefetcher could grab the 64-byte -* chunk and get a valid (!= * 0xffffffff) byte count but -* stale data, and end up sending the wrong data. -*/ -rte_io_wmb (); -if (likely (pkt->data_len)) - dseg->byte_count =rte_cpu_to_be_32 (pkt->data_len); -else -/* -* Zero length segment is treated as inline segment -* with zero data. -*/ - dseg->byte_count =RTE_BE32 (0x80000000 ); -/* -* Fill the control parameters for this packet. -* For raw Ethernet, the SOLICIT flag is used to indicate that no icrc -* should be calculated -*/ - ctrl->srcrb_flags = -rte_cpu_to_be_32 (MLX4_WQE_CTRL_SOLICIT | - (send_flags &MLX4_WQE_CTRL_CQ_UPDATE )); +/* Write the first DWORD of each TXBB save earlier. */ +if (pv_counter) { +/* Need a barrier here before writing the byte_count. */ +rte_io_wmb (); +for (--pv_counter; pv_counter >=0 ; pv_counter--) + pv[pv_counter].dseg->byte_count = pv[pv_counter].val; + } +/* Fill the control parameters for this packet. */ ctrl->fence_size = (wqe_real_size >>4 ) &0x3f ;/* * The caller should prepare "imm" in advance in order to support * VF to VF communication (when the device is a virtual-function * device (VF)). -*/ +*/ ctrl->imm =0 ;/* +* For raw Ethernet, the SOLICIT flag is used to indicate that no icrc +* should be calculated. +*/ + txq->elts_comp_cd -= nr_txbbs; +if (unlikely (txq->elts_comp_cd <=0 )) { + txq->elts_comp_cd = txq->elts_comp_cd_init; + srcrb_flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT | +MLX4_WQE_CTRL_CQ_UPDATE ); + }else { + srcrb_flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT ); + } + ctrl->srcrb_flags = srcrb_flags; +/* * Make sure descriptor is fully written before * setting ownership bit (because HW can start * executing as soon as we do). */ -rte_wmb (); - ctrl->owner_opcode = -rte_cpu_to_be_32 (MLX4_OPCODE_SEND | - ((sq->head & sq->txbb_cnt) ? -MLX4_BIT_WQE_OWN :0 )); +rte_wmb (); + ctrl->owner_opcode =rte_cpu_to_be_32 (owner_opcode | + ((sq->head & sq->txbb_cnt) ? +MLX4_BIT_WQE_OWN :0 )); sq->head += nr_txbbs;return 0 ; err:
@@ -428,14 +474,13 @@struct txq *txq = (struct txq *)dpdk_txq;unsigned int elts_head = txq->elts_head;const unsigned int elts_n = txq->elts_n; -unsigned int elts_comp_cd = txq->elts_comp_cd;unsigned int elts_comp =0 ;unsigned int bytes_sent =0 ;unsigned int i;unsigned int max;int err; -assert (elts_comp_cd !=0 ); +assert (txq->elts_comp_cd !=0 );mlx4_txq_complete (txq); max = (elts_n - (elts_head - txq->elts_tail));if (max > elts_n)
@@ -454,8 +499,6 @@ (((elts_head +1 ) == elts_n) ?0 : elts_head +1 );struct txq_elt *elt_next = &(*txq->elts)[elts_head_next];struct txq_elt *elt = &(*txq->elts)[elts_head]; -unsigned int segs = buf->nb_segs; -uint32_t send_flags =0 ;/* Clean up old buffer. */ if (likely (elt->buf !=NULL )) {
@@ -473,34 +516,16 @@ tmp = next; }while (tmp !=NULL ); } -/* Request Tx completion. */ -if (unlikely (--elts_comp_cd ==0 )) { - elts_comp_cd = txq->elts_comp_cd_init; - ++elts_comp; - send_flags |=MLX4_WQE_CTRL_CQ_UPDATE ; - } -if (likely (segs ==1 )) { -/* Update element. */ - elt->buf = buf; -RTE_MBUF_PREFETCH_TO_FREE (elt_next->buf); -/* post the pkt for sending */ - err =mlx4_post_send (txq, buf, send_flags); -if (unlikely (err)) { -if (unlikely (send_flags & -MLX4_WQE_CTRL_CQ_UPDATE )) { - elts_comp_cd =1 ; - --elts_comp; - } - elt->buf =NULL ; - goto stop; - } - elt->buf = buf; - bytes_sent += buf->pkt_len; - }else { - err = -EINVAL ; - rte_errno = -err; +RTE_MBUF_PREFETCH_TO_FREE (elt_next->buf); +/* post the packet for sending. */ + err =mlx4_post_send (txq, buf); +if (unlikely (err)) { + elt->buf =NULL ; goto stop; } + elt->buf = buf; + bytes_sent += buf->pkt_len; + ++elts_comp; elts_head = elts_head_next; } stop:
@@ -516,7 +541,6 @@rte_write32 (txq->msq.doorbell_qpn, txq->msq.db); txq->elts_head = elts_head; txq->elts_comp += elts_comp; - txq->elts_comp_cd = elts_comp_cd;return i; }
drivers/net/mlx4/mlx4_rxtx.h +4 -2
@@ -103,13 +103,15 @@ struct txq {struct mlx4_cq mcq;/**< Info for directly manipulating the CQ. */ unsigned int elts_head;/**< Current index in (*elts)[]. */ unsigned int elts_tail;/**< First element awaiting completion. */ -unsigned int elts_comp;/**< Number of completion requests. */ -unsigned int elts_comp_cd;/**< Countdown for next completion. */ +unsigned int elts_comp;/**< Number of pkts waiting for completion. */ +int elts_comp_cd;/**< Countdown for next completion. */ unsigned int elts_comp_cd_init;/**< Initial value for countdown. */ unsigned int elts_n;/**< (*elts)[] length. */ struct txq_elt (*elts)[];/**< Tx elements. */ struct mlx4_txq_stats stats;/**< Tx queue counters. */ uint32_t max_inline;/**< Max inline send size. */ +char *bounce_buf; +/**< memory used for storing the first DWORD of data TXBBs. */ struct {const struct rte_mempool *mp;/**< Cached memory pool. */ struct ibv_mr *mr;/**< Memory region (for mp). */
drivers/net/mlx4/mlx4_txq.c +9 -3
@@ -83,8 +83,14 @@rte_calloc_socket ("TXQ" ,1 ,sizeof (*elts),0 , txq->ctrl.socket);int ret =0 ; -if (elts ==NULL ) { -ERROR ("%p: can't allocate packets array" , (void *)txq); +/* Allocate Bounce-buf memory */ + txq->bounce_buf = (char *)rte_zmalloc_socket ("TXQ" , +MLX4_MAX_WQE_SIZE , +RTE_CACHE_LINE_MIN_SIZE , + txq->ctrl.socket); + +if ((elts ==NULL ) || (txq->bounce_buf ==NULL )) { +ERROR ("%p: can't allocate TXQ memory" , (void *)txq); ret =ENOMEM ; goto error; }
@@ -110,6 +116,7 @@assert (ret ==0 );return 0 ; error: +rte_free (txq->bounce_buf);rte_free (elts);DEBUG ("%p: failed, freed everything" , (void *)txq);assert (ret >0 );
@@ -303,7 +310,6 @@ struct txq_mp2mr_mbuf_check_data {struct mlx4dv_obj mlxdv;struct mlx4dv_qp dv_qp;struct mlx4dv_cq dv_cq; -struct txq tmpl = { .ctrl = { .priv = priv,
Signature · 1 line
1.8.3.1
PATCH v2 4/6 net/mlx4: get back Tx checksum offloads
In reply to Matan AzradFrom: Moti Haimovsky <[email protected]>
This patch adds hardware offloading support for IPV4, UDP and TCP checksum calculation.
This commit also includes support for offloading IPV4, UDP and TCP tunnel checksum calculation to the hardware.
--- drivers/net/mlx4/mlx4.c | 9 +++++++++ drivers/net/mlx4/mlx4.h | 2 ++ drivers/net/mlx4/mlx4_ethdev.c | 6 ++++++ drivers/net/mlx4/mlx4_prm.h | 2 ++ drivers/net/mlx4/mlx4_rxtx.c | 25 +++++++++++++++++++++---- drivers/net/mlx4/mlx4_rxtx.h | 2 ++ drivers/net/mlx4/mlx4_txq.c | 2 ++ 7 files changed, 44 insertions(+), 4 deletions(-)
drivers/net/mlx4/mlx4.c +9 -0
@@ -397,6 +397,7 @@ struct mlx4_conf { .ports.present = 0, };unsigned int vf; +unsigned int tunnel_en;int i; (void )pci_drv;
@@ -456,6 +457,9 @@ struct mlx4_conf { rte_errno =ENODEV ; goto error; } +/* Only cx3-pro supports L3 tunneling */ + tunnel_en = (device_attr.vendor_part_id == +PCI_DEVICE_ID_MELLANOX_CONNECTX3PRO );INFO ("%u port(s) detected" , device_attr.phys_port_cnt); conf.ports.present |= (UINT64_C (1 ) << device_attr.phys_port_cnt) -1 ;if (mlx4_args (pci_dev->device.devargs, &conf)) {
@@ -529,6 +533,11 @@ struct mlx4_conf { priv->pd = pd; priv->mtu =ETHER_MTU ; priv->vf = vf; + priv->hw_csum = + !!(device_attr.device_cap_flags &IBV_DEVICE_RAW_IP_CSUM ); + priv->hw_csum_l2tun = tunnel_en; +DEBUG ("L2 tunnel checksum offloads are %ssupported" , + (priv->hw_csum_l2tun ?"" :"not " ));/* Configure the first MAC address by default. */ if (mlx4_get_mac (priv, &mac.addr_bytes)) { ERROR("cannot get MAC address, is mlx4_en loaded?"
drivers/net/mlx4/mlx4.h +2 -0
@@ -93,6 +93,8 @@ struct priv { unsigned int vf:1; /* This is a VF device. */ unsigned int intr_alarm:1; /* An interrupt alarm is scheduled. */ unsigned int isolated:1; /* Toggle isolated mode. */ + unsigned int hw_csum:1; /* Checksum offload is supported. */ + unsigned int hw_csum_l2tun:1; /* Checksum support for L2 tunnels. */struct rte_intr_handle intr_handle;/* Port interrupt handle. */ struct rte_flow_drop *flow_drop_queue;/* Flow drop queue. */ LIST_HEAD(mlx4_flows, rte_flow) flows;
drivers/net/mlx4/mlx4_ethdev.c +6 -0
@@ -553,6 +553,12 @@ info->max_mac_addrs =1 ; info->rx_offload_capa =0 ; info->tx_offload_capa =0 ; +if (priv->hw_csum) + info->tx_offload_capa |= (DEV_TX_OFFLOAD_IPV4_CKSUM | +DEV_TX_OFFLOAD_UDP_CKSUM | +DEV_TX_OFFLOAD_TCP_CKSUM ); +if (priv->hw_csum_l2tun) + info->tx_offload_capa |=DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM ;if (mlx4_get_ifname (priv, &ifname) ==0 ) info->if_index =if_nametoindex (ifname); info->speed_capa =
drivers/net/mlx4/mlx4_prm.h +2 -0
@@ -64,6 +64,8 @@/* Work queue element (WQE) flags. */ #define MLX4_BIT_WQE_OWN 0x80000000 +#define MLX4_WQE_CTRL_IIP_HDR_CSUM (1 << 28) +#define MLX4_WQE_CTRL_IL4_HDR_CSUM (1 << 27)#define MLX4_SIZE_TO_TXBBS (size) \ (RTE_ALIGN((size), (MLX4_TXBB_SIZE)) >> (MLX4_TXBB_SHIFT))
drivers/net/mlx4/mlx4_rxtx.c +21 -4
@@ -433,12 +433,29 @@ struct pv { txq->elts_comp_cd -= nr_txbbs;if (unlikely (txq->elts_comp_cd <=0 )) { txq->elts_comp_cd = txq->elts_comp_cd_init; - srcrb_flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT | -MLX4_WQE_CTRL_CQ_UPDATE ); + srcrb_flags =MLX4_WQE_CTRL_SOLICIT |MLX4_WQE_CTRL_CQ_UPDATE ; }else { - srcrb_flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT ); + srcrb_flags =MLX4_WQE_CTRL_SOLICIT ; } - ctrl->srcrb_flags = srcrb_flags; +/* Enable HW checksum offload if requested */ +if (txq->csum && + (pkt->ol_flags & + (PKT_TX_IP_CKSUM |PKT_TX_TCP_CKSUM |PKT_TX_UDP_CKSUM ))) { +const uint64_t is_tunneled = pkt->ol_flags & + (PKT_TX_TUNNEL_GRE | +PKT_TX_TUNNEL_VXLAN ); + +if (is_tunneled && txq->csum_l2tun) { + owner_opcode |=MLX4_WQE_CTRL_IIP_HDR_CSUM | +MLX4_WQE_CTRL_IL4_HDR_CSUM ; +if (pkt->ol_flags &PKT_TX_OUTER_IP_CKSUM ) + srcrb_flags |=MLX4_WQE_CTRL_IP_HDR_CSUM ; + }else { + srcrb_flags |=MLX4_WQE_CTRL_IP_HDR_CSUM | +MLX4_WQE_CTRL_TCP_UDP_CSUM ; + } + } + ctrl->srcrb_flags =rte_cpu_to_be_32 (srcrb_flags);/* * Make sure descriptor is fully written before * setting ownership bit (because HW can start
drivers/net/mlx4/mlx4_rxtx.h +2 -0
@@ -110,6 +110,8 @@ struct txq {struct txq_elt (*elts)[];/**< Tx elements. */ struct mlx4_txq_stats stats;/**< Tx queue counters. */ uint32_t max_inline;/**< Max inline send size. */ + uint32_t csum:1; /**< Checksum is supported and enabled */ + uint32_t csum_l2tun:1; /**< L2 tun Checksum is supported and enabled */char *bounce_buf;/**< memory used for storing the first DWORD of data TXBBs. */ struct {
drivers/net/mlx4/mlx4_txq.c +2 -0
@@ -340,6 +340,8 @@ struct txq_mp2mr_mbuf_check_data { (void *)dev, strerror(rte_errno)); goto error; } + tmpl.csum = priv->hw_csum; + tmpl.csum_l2tun = priv->hw_csum_l2tun;DEBUG ("priv->device_attr.max_qp_wr is %d" , priv->device_attr.max_qp_wr); DEBUG("priv->device_attr.max_sge is %d",
Signature · 1 line
1.8.3.1
PATCH v2 5/6 net/mlx4: get back Rx checksum offloads
In reply to Matan AzradFrom: Moti Haimovsky <[email protected]>
This patch adds hardware offloading support for IPV4, UDP and TCP checksum verification.
This commit also includes support for offloading IPV4, UDP and TCP tunnel checksum verification to the hardware.
--- drivers/net/mlx4/mlx4.c | 2 + drivers/net/mlx4/mlx4_ethdev.c | 8 ++- drivers/net/mlx4/mlx4_prm.h | 19 +++++++ drivers/net/mlx4/mlx4_rxq.c | 5 ++ drivers/net/mlx4/mlx4_rxtx.c | 120 ++++++++++++++++++++++++++++++++++++++++- drivers/net/mlx4/mlx4_rxtx.h | 2 + 6 files changed, 152 insertions(+), 4 deletions(-)
drivers/net/mlx4/mlx4.c +2 -0
@@ -535,6 +535,8 @@ struct mlx4_conf { priv->vf = vf; priv->hw_csum = !!(device_attr.device_cap_flags &IBV_DEVICE_RAW_IP_CSUM ); +DEBUG ("checksum offloading is %ssupported" , + (priv->hw_csum ?"" :"not " )); priv->hw_csum_l2tun = tunnel_en;DEBUG ("L2 tunnel checksum offloads are %ssupported" , (priv->hw_csum_l2tun ?"" :"not " ));
drivers/net/mlx4/mlx4_ethdev.c +6 -2
@@ -553,10 +553,14 @@ info->max_mac_addrs =1 ; info->rx_offload_capa =0 ; info->tx_offload_capa =0 ; -if (priv->hw_csum) +if (priv->hw_csum) { info->tx_offload_capa |= (DEV_TX_OFFLOAD_IPV4_CKSUM | -DEV_TX_OFFLOAD_UDP_CKSUM | +DEV_TX_OFFLOAD_UDP_CKSUM |DEV_TX_OFFLOAD_TCP_CKSUM ); + info->rx_offload_capa |= (DEV_RX_OFFLOAD_IPV4_CKSUM | +DEV_RX_OFFLOAD_UDP_CKSUM | +DEV_RX_OFFLOAD_TCP_CKSUM ); + }if (priv->hw_csum_l2tun) info->tx_offload_capa |=DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM ;if (mlx4_get_ifname (priv, &ifname) ==0 )
drivers/net/mlx4/mlx4_prm.h +19 -0
@@ -70,6 +70,25 @@#define MLX4_SIZE_TO_TXBBS (size) \ (RTE_ALIGN((size), (MLX4_TXBB_SIZE)) >> (MLX4_TXBB_SHIFT)) +/* Generic macro to convert MLX4 to IBV flags. */ +#define MLX4_TRANSPOSE (val, from, to) \ + (__extension__({ \ + typeof(val) _val = (val); \ + typeof(from) _from = (from); \ + typeof(to) _to = (to); \ + (((_from) >= (_to)) ? \ + (((_val) & (_from)) / ((_from) / (_to))) : \ + (((_val) & (_from)) * ((_to) / (_from)))); \ + })) + +/* CQE checksum flags */ +enum { +MLX4_CQE_L2_TUNNEL_IPV4 = (int )(1U <<25 ), +MLX4_CQE_L2_TUNNEL_L4_CSUM = (int )(1U <<26 ), +MLX4_CQE_L2_TUNNEL = (int )(1U <<27 ), +MLX4_CQE_L2_TUNNEL_IPOK = (int )(1U <<31 ), +}; +/* Send queue information. */ struct mlx4_sq {char *buf;/**< SQ buffer. */
drivers/net/mlx4/mlx4_rxq.c +5 -0
@@ -267,6 +267,11 @@int ret; (void )conf;/* Thresholds configuration (ignored). */ +/* Toggle Rx checksum offload if hardware supports it. */ +if (priv->hw_csum) + tmpl.csum = !!dev->data->dev_conf.rxmode.hw_ip_checksum; +if (priv->hw_csum_l2tun) + tmpl.csum_l2tun = !!dev->data->dev_conf.rxmode.hw_ip_checksum; mb_len =rte_pktmbuf_data_room_size (mp);/* Enable scattered packets support for this queue if necessary. */ assert (mb_len >=RTE_PKTMBUF_HEADROOM );
drivers/net/mlx4/mlx4_rxtx.c +118 -2
144 lines not on this page · raw message
drivers/net/mlx4/mlx4_rxtx.h +2 -0
@@ -80,6 +80,8 @@ struct rxq { } hw;struct mlx4_cq mcq;/**< Info for directly manipulating the CQ. */ unsigned int sge_n;/**< Log 2 of SGEs number. */ + unsigned int csum:1; /**< Enable checksum offloading. */ + unsigned int csum_l2tun:1; /**< Enable checksum for L2 tunnels. */struct mlx4_rxq_stats stats;/**< Rx queue counters. */ unsigned int socket;/**< CPU socket ID for allocations. */ };
Signature · 1 line
1.8.3.1
Re: [PATCH v2 5/6] net/mlx4: get back Rx checksum offloads
Quoted 8 lines · Matan Azrad
From: Moti Haimovsky <[email protected]>
This patch adds hardware offloading support for IPV4, UDP and TCP checksum verification.
This commit also includes support for offloading IPV4, UDP and TCP tunnel checksum verification to the hardware.Signed-off-by Vasily Philipov <[email protected]>
<...>
Quoted 24 lines
drivers/net/mlx4/mlx4_rxtx.c +24
-0+/** +* Get Rx checksum CQE flags. +* +* @param cqe +* Pointer to cqe structure. +* @param csum +* Rx checksum enable flag +* @param csum_l2tun +* RX L2-tun checksum enable flag +* +* @return +* CQE's flags. +*/ +static inline uint32_t +mlx4_cqe_flags (struct mlx4_cqe *cqe, +int csum,unsigned int csum_l2tun) +{ +uint32_t flags =0 ; + +/* +* The relevant bits are in different locations on their +* CQE fields therefore we can join them in one 32bit +* variable. +*/
drivers/net/mlx4/mlx4_rxtx.c struct pv { · line 665
Quoted 10 lines
drivers/net/mlx4/mlx4_rxtx.c +10
-0+if (csum) + flags =rte_be_to_cpu_32 (cqe->status) & +MLX4_CQE_STATUS_IPV4_CSUM_OK ; +if (csum_l2tun) + flags |=rte_be_to_cpu_32 (cqe->vlan_my_qpn) & + (MLX4_CQE_L2_TUNNEL | +MLX4_CQE_L2_TUNNEL_IPOK | +MLX4_CQE_L2_TUNNEL_L4_CSUM | +MLX4_CQE_L2_TUNNEL_IPV4 ); +return flags;
Wrong indentation is triggering a compiler warning here:
.../dpdk/drivers/net/mlx4/mlx4_rxtx.c: In function ‘mlx4_cqe_flags’:.../dpdk/drivers/net/mlx4/mlx4_rxtx.c:673:2: error: this ‘if’ clause does not guard... [-Werror=misleading-indentation]
if (csum_l2tun)
^~.../dpdk/drivers/net/mlx4/mlx4_rxtx.c:679:3: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the ‘if’
return flags;
^~~~~~
<...>
PATCH v2 6/6 net/mlx4: add loopback Tx from VF
In reply to Matan AzradFrom: Moti Haimovsky <[email protected]>
This patch adds loopback functionality used when the chip is a VF in order to enable packet transmission between VFs and between VFs and PF.
--- drivers/net/mlx4/mlx4_rxtx.c | 38 ++++++++++++++++++++++++++------------ drivers/net/mlx4/mlx4_rxtx.h | 2 ++ drivers/net/mlx4/mlx4_txq.c | 2 ++ 3 files changed, 30 insertions(+), 12 deletions(-)
drivers/net/mlx4/mlx4_rxtx.c +26 -12
@@ -320,10 +320,13 @@ struct pv {struct mlx4_wqe_data_seg *dseg;struct mlx4_sq *sq = &txq->msq;struct rte_mbuf *buf; +union { +uint32_t flags; +uint16_t flags16[2 ]; + } srcrb;uint32_t head_idx = sq->head & sq->txbb_cnt_mask;uint32_t lkey;uintptr_t addr; -uint32_t srcrb_flags;uint32_t owner_opcode =MLX4_OPCODE_SEND ;uint32_t byte_count;int wqe_real_size;
@@ -421,21 +424,15 @@ struct pv {/* Fill the control parameters for this packet. */ ctrl->fence_size = (wqe_real_size >>4 ) &0x3f ;/* -* The caller should prepare "imm" in advance in order to support -* VF to VF communication (when the device is a virtual-function -* device (VF)). -*/ - ctrl->imm =0 ; -/* * For raw Ethernet, the SOLICIT flag is used to indicate that no icrc * should be calculated. */ txq->elts_comp_cd -= nr_txbbs;if (unlikely (txq->elts_comp_cd <=0 )) { txq->elts_comp_cd = txq->elts_comp_cd_init; - srcrb_flags =MLX4_WQE_CTRL_SOLICIT |MLX4_WQE_CTRL_CQ_UPDATE ; + srcrb.flags =MLX4_WQE_CTRL_SOLICIT |MLX4_WQE_CTRL_CQ_UPDATE ; }else { - srcrb_flags =MLX4_WQE_CTRL_SOLICIT ; + srcrb.flags =MLX4_WQE_CTRL_SOLICIT ; }/* Enable HW checksum offload if requested */ if (txq->csum &&
@@ -449,13 +446,30 @@ struct pv { owner_opcode |=MLX4_WQE_CTRL_IIP_HDR_CSUM |MLX4_WQE_CTRL_IL4_HDR_CSUM ;if (pkt->ol_flags &PKT_TX_OUTER_IP_CKSUM ) - srcrb_flags |=MLX4_WQE_CTRL_IP_HDR_CSUM ; + srcrb.flags |=MLX4_WQE_CTRL_IP_HDR_CSUM ; }else { - srcrb_flags |=MLX4_WQE_CTRL_IP_HDR_CSUM | + srcrb.flags |=MLX4_WQE_CTRL_IP_HDR_CSUM |MLX4_WQE_CTRL_TCP_UDP_CSUM ; } } - ctrl->srcrb_flags =rte_cpu_to_be_32 (srcrb_flags); +/* +* convert flags to BE before adding the mac address (if at all) +* to it +*/ + srcrb.flags =rte_cpu_to_be_32 (srcrb.flags); +if (txq->lb) { +/* +* Copy destination mac address to the wqe, +* this allows loopback in eSwitch, so that VFs and PF +* can communicate with each other. +*/ + srcrb.flags16[0] = *(rte_pktmbuf_mtod(pkt, uint16_t *)); + ctrl->imm = *(rte_pktmbuf_mtod_offset (pkt ,uint32_t *, + sizeof(uint16_t))); + }else { + ctrl->imm =0 ; + } + ctrl->srcrb_flags = srcrb.flags;/* * Make sure descriptor is fully written before * setting ownership bit (because HW can start
drivers/net/mlx4/mlx4_rxtx.h +2 -0
@@ -114,6 +114,8 @@ struct txq {uint32_t max_inline;/**< Max inline send size. */ uint32_t csum:1; /**< Checksum is supported and enabled */ uint32_t csum_l2tun:1; /**< L2 tun Checksum is supported and enabled */ + uint32_t lb:1; +/**< Whether pkts should be looped-back by eswitch or not */ char *bounce_buf;/**< memory used for storing the first DWORD of data TXBBs. */ struct {
drivers/net/mlx4/mlx4_txq.c +2 -0
@@ -415,6 +415,8 @@ struct txq_mp2mr_mbuf_check_data { (void *)dev, strerror(rte_errno)); goto error; } +/* If a VF device - need to loopback xmitted packets */ + tmpl.lb = !!(priv->vf);/* Clean up txq in case we're reinitializing it. */ DEBUG ("%p: cleaning-up old txq just in case" , (void *)txq);mlx4_txq_cleanup (txq);
Signature · 1 line
1.8.3.1
Re: [PATCH v2 0/6] new mlx4 datapath bypassing ibverbs
In reply to Matan AzradQuoted 6 lines · Matan Azrad
v2:
Rearange patches.
Semantics.
Enhancements.
Fix compilation issues.
Quoted 7 lines
Moti Haimovsky (6):
net/mlx4: add simple Tx bypassing ibverbs
net/mlx4: get back Rx flow functionality
net/mlx4: support multi-segments Tx
net/mlx4: get back Tx checksum offloads
net/mlx4: get back Rx checksum offloads
net/mlx4: add loopback Tx from VF
While sending new version, can you please rebase on latest next-net? Although it is easy to resolve this cause a merge conflict.
v3 cover new mlx4 datapath bypassing ibverbs
In reply to Matan AzradTook me a while to finally review this series. Since there is not much time left, I'm taking care of v3 with several minor changes summarized below and my ack included directly.
v3 (Adrien):
- Drop a few unrelated or unnecessary changes such as the removal of MLX4_PMD_TX_MP_CACHE.
- Move device checksum support detection code to its previous location.
- Fix include guard in mlx4_prm.h.
- Reorder #includes alphabetically.
- Replace MLX4_TRANSPOSE() macro with documented inline function.
- Remove extra spaces and blank lines.
- Use uint8_t * instead of char * for buffers.
- Replace mlx4_get_cqe() macro with a documented inline function.
- Replace several unsigned int with uint32_t.
- Add consistency to field names (sge_n => sges_n).
- Make mbuf size checks in RX queue setup function similar to mlx5.
- Update various comments.
- Fix indentation.
- Replace run-time endian conversion with static ones where possible.
- Reorder fields in struct rxq and struct txq for consistency, remove one level of unnecessary inner structures.
- Fix memory leak on Tx bounce buffer.
- Update commit logs.
- Fix remaining checkpatch warnings.
v2 (Matan):
Rearange patches.
Semantics.
Enhancements.
Fix compilation issues.
Moti Haimovsky (6):
net/mlx4: add simple Tx bypassing Verbs net/mlx4: restore full Rx support bypassing Verbs net/mlx4: restore Tx gather support net/mlx4: restore Tx checksum offloads net/mlx4: restore Rx offloads
net/mlx4: add loopback Tx from VF
drivers/net/mlx4/mlx4.c | 11 + drivers/net/mlx4/mlx4.h | 2 + drivers/net/mlx4/mlx4_ethdev.c | 10 + drivers/net/mlx4/mlx4_prm.h | 152 +++++++ drivers/net/mlx4/mlx4_rxq.c | 179 ++++++--- drivers/net/mlx4/mlx4_rxtx.c | 768 ++++++++++++++++++++++++++---------- drivers/net/mlx4/mlx4_rxtx.h | 54 +-- drivers/net/mlx4/mlx4_txq.c | 67 +++- drivers/net/mlx4/mlx4_utils.h | 20 + mk/rte.app.mk | 2 +- 10 files changed, 975 insertions(+), 290 deletions(-) create mode 100644 drivers/net/mlx4/mlx4_prm.h
Signature · 1 line
2.1.4
PATCH v3 1/6 net/mlx4: add simple Tx bypassing Verbs
From: Moti Haimovsky <[email protected]>
Modify PMD to send single-buffer packets directly to the device bypassing the Verbs Tx post and poll routines.
--- drivers/net/mlx4/mlx4_prm.h | 120 ++++++++++++++ drivers/net/mlx4/mlx4_rxtx.c | 337 ++++++++++++++++++++++++++++---------- drivers/net/mlx4/mlx4_rxtx.h | 28 ++-- drivers/net/mlx4/mlx4_txq.c | 51 ++++++ mk/rte.app.mk | 2 +- 5 files changed, 436 insertions(+), 102 deletions(-)
drivers/net/mlx4/mlx4_prm.h new file +120 -0
@@ -0,0 +1,120 @@ +/*- +* BSD LICENSE +* +* Copyright 2017 6WIND S.A. +* Copyright 2017 Mellanox +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of 6WIND S.A. nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef MLX4_PRM_H_ +#define MLX4_PRM_H_ + +#include <rte_atomic.h> +#include <rte_branch_prediction.h> +#include <rte_byteorder.h> + +/* Verbs headers do not support -pedantic. */ +#ifdef PEDANTIC +#pragma GCC diagnostic ignored "-Wpedantic" +#endif +#include <infiniband/mlx4dv.h> +#include <infiniband/verbs.h> +#ifdef PEDANTIC +#pragma GCC diagnostic error "-Wpedantic" +#endif + +/* ConnectX-3 Tx queue basic block. */ +#define MLX4_TXBB_SHIFT 6 +#define MLX4_TXBB_SIZE (1 << MLX4_TXBB_SHIFT) + +/* Typical TSO descriptor with 16 gather entries is 352 bytes. */ +#define MLX4_MAX_WQE_SIZE 512 +#define MLX4_MAX_WQE_TXBBS (MLX4_MAX_WQE_SIZE / MLX4_TXBB_SIZE) + +/* Send queue stamping/invalidating information. */ +#define MLX4_SQ_STAMP_STRIDE 64 +#define MLX4_SQ_STAMP_DWORDS (MLX4_SQ_STAMP_STRIDE / 4) +#define MLX4_SQ_STAMP_SHIFT 31 +#define MLX4_SQ_STAMP_VAL 0x7fffffff + +/* Work queue element (WQE) flags. */ +#define MLX4_BIT_WQE_OWN 0x80000000 + +#define MLX4_SIZE_TO_TXBBS (size) \ + (RTE_ALIGN((size), (MLX4_TXBB_SIZE)) >> (MLX4_TXBB_SHIFT)) + +/* Send queue information. */ +struct mlx4_sq { +uint8_t *buf;/**< SQ buffer. */ +uint8_t *eob;/**< End of SQ buffer */ +uint32_t head;/**< SQ head counter in units of TXBBS. */ +uint32_t tail;/**< SQ tail counter in units of TXBBS. */ +uint32_t txbb_cnt;/**< Num of WQEBB in the Q (should be ^2). */ +uint32_t txbb_cnt_mask;/**< txbbs_cnt mask (txbb_cnt is ^2). */ +uint32_t headroom_txbbs;/**< Num of txbbs that should be kept free. */ +uint32_t *db;/**< Pointer to the doorbell. */ +uint32_t doorbell_qpn;/**< qp number to write to the doorbell. */ +}; + +#define mlx4_get_send_wqe (sq, n) ((sq)->buf + ((n) * (MLX4_TXBB_SIZE))) + +/* Completion queue information. */ +struct mlx4_cq { +uint8_t *buf;/**< Pointer to the completion queue buffer. */ +uint32_t cqe_cnt;/**< Number of entries in the queue. */ +uint32_t cqe_64:1 ;/**< CQ entry size is 64 bytes. */ +uint32_t cons_index;/**< Last queue entry that was handled. */ +uint32_t *set_ci_db;/**< Pointer to the completion queue doorbell. */ +}; + +/** +* Retrieve a CQE entry from a CQ. +* +* cqe = cq->buf + cons_index * cqe_size + cqe_offset +* +* Where cqe_size is 32 or 64 bytes and cqe_offset is 0 or 32 (depending on +* cqe_size). +* +* @param cq +* CQ to retrieve entry from. +* @param index +* Entry index. +* +* @return +* Pointer to CQE entry. +*/ +static inline struct mlx4_cqe * +mlx4_get_cqe (struct mlx4_cq *cq,uint32_t index) +{ +return (struct mlx4_cqe *)(cq->buf + + ((index & (cq->cqe_cnt -1 )) << + (5 + cq->cqe_64)) + + (cq->cqe_64 <<5 )); +} + +#endif /* MLX4_PRM_H_ */
drivers/net/mlx4/mlx4_rxtx.c +249 -88
411 lines not on this page · raw message
drivers/net/mlx4/mlx4_rxtx.h +15 -13
@@ -40,6 +40,7 @@#ifdef PEDANTIC #pragma GCC diagnostic ignored "-Wpedantic"#endif +#include <infiniband/mlx4dv.h> #include <infiniband/verbs.h> #ifdef PEDANTIC #pragma GCC diagnostic error "-Wpedantic"
@@ -50,6 +51,7 @@#include <rte_mempool.h> #include "mlx4.h" +#include "mlx4_prm.h" /** Rx queue counters. */ struct mlx4_rxq_stats {
@@ -85,8 +87,6 @@ struct rxq {/** Tx element. */ struct txq_elt { -struct ibv_send_wr wr;/* Work request. */ -struct ibv_sge sge;/* Scatter/gather element. */ struct rte_mbuf *buf;/**< Buffer. */ };
@@ -100,24 +100,26 @@ struct mlx4_txq_stats {/** Tx queue descriptor. */ struct txq { -struct priv *priv;/**< Back pointer to private data. */ -struct { -const struct rte_mempool *mp;/**< Cached memory pool. */ -struct ibv_mr *mr;/**< Memory region (for mp). */ -uint32_t lkey;/**< mr->lkey copy. */ - } mp2mr[MLX4_PMD_TX_MP_CACHE ];/**< MP to MR translation table. */ -struct ibv_cq *cq;/**< Completion queue. */ -struct ibv_qp *qp;/**< Queue pair. */ -uint32_t max_inline;/**< Max inline send size. */ -unsigned int elts_n;/**< (*elts)[] length. */ -struct txq_elt (*elts)[];/**< Tx elements. */ +struct mlx4_sq msq;/**< Info for directly manipulating the SQ. */ +struct mlx4_cq mcq;/**< Info for directly manipulating the CQ. */ unsigned int elts_head;/**< Current index in (*elts)[]. */ unsigned int elts_tail;/**< First element awaiting completion. */ unsigned int elts_comp;/**< Number of completion requests. */ unsigned int elts_comp_cd;/**< Countdown for next completion. */ unsigned int elts_comp_cd_init;/**< Initial value for countdown. */ +unsigned int elts_n;/**< (*elts)[] length. */ +struct txq_elt (*elts)[];/**< Tx elements. */ struct mlx4_txq_stats stats;/**< Tx queue counters. */ +uint32_t max_inline;/**< Max inline send size. */ +struct { +const struct rte_mempool *mp;/**< Cached memory pool. */ +struct ibv_mr *mr;/**< Memory region (for mp). */ +uint32_t lkey;/**< mr->lkey copy. */ + } mp2mr[MLX4_PMD_TX_MP_CACHE ];/**< MP to MR translation table. */ +struct priv *priv;/**< Back pointer to private data. */ unsigned int socket;/**< CPU socket ID for allocations. */ +struct ibv_cq *cq;/**< Completion queue. */ +struct ibv_qp *qp;/**< Queue pair. */ };/* mlx4_rxq.c */
drivers/net/mlx4/mlx4_txq.c +51 -0
75 lines not on this page · raw message
mk/rte.app.mk +1 -1
@@ -133,7 +133,7 @@ ifeq ($(CONFIG_RTE_LIBRTE_KNI),y) _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_KNI) += -lrte_pmd_kni endif _LDLIBS-$(CONFIG_RTE_LIBRTE_LIO_PMD) += -lrte_pmd_lio -_LDLIBS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += -lrte_pmd_mlx4 -libverbs +_LDLIBS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += -lrte_pmd_mlx4 -libverbs -lmlx4 _LDLIBS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += -lrte_pmd_mlx5 -libverbs -lmlx5 _LDLIBS-$(CONFIG_RTE_LIBRTE_NFP_PMD) += -lrte_pmd_nfp _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += -lrte_pmd_null
Signature · 1 line
2.1.4
PATCH v3 2/6 net/mlx4: restore full Rx support bypassing Verbs
In reply to Adrien MazarguilFrom: Moti Haimovsky <[email protected]>
This patch adds support for accessing the hardware directly when handling Rx packets eliminating the need to use Verbs in the Rx data path.
The number of scatters is calculated on the fly, according to the maximum expected packet size.
--- drivers/net/mlx4/mlx4_rxq.c | 174 ++++++++++++++++++---------- drivers/net/mlx4/mlx4_rxtx.c | 226 +++++++++++++++++++++---------------- drivers/net/mlx4/mlx4_rxtx.h | 19 ++-- drivers/net/mlx4/mlx4_utils.h | 20 ++++ 4 files changed, 270 insertions(+), 169 deletions(-)
drivers/net/mlx4/mlx4_rxq.c +114 -60
@@ -51,6 +51,7 @@#pragma GCC diagnostic error "-Wpedantic"#endif +#include <rte_byteorder.h> #include <rte_common.h> #include <rte_errno.h> #include <rte_ethdev.h>
@@ -77,20 +78,18 @@ static int mlx4_rxq_alloc_elts(struct rxq *rxq, unsigned int elts_n) {unsigned int i; -struct rxq_elt (*elts)[elts_n] = -rte_calloc_socket ("RXQ elements" ,1 ,sizeof (*elts),0 , - rxq->socket); +const uint32_t sges_n =1 << rxq->sges_n; +struct rte_mbuf *(*elts)[elts_n] = +rte_calloc_socket ("RXQ" ,1 ,sizeof (*elts),0 , rxq->socket); +assert (rte_is_power_of_2 (elts_n));if (elts ==NULL ) { rte_errno =ENOMEM ;ERROR ("%p: can't allocate packets array" , (void *)rxq); goto error; } -/* For each WR (packet). */ for (i =0 ; (i != elts_n); ++i) { -struct rxq_elt *elt = &(*elts)[i]; -struct ibv_recv_wr *wr = &elt->wr; -struct ibv_sge *sge = &(*elts)[i].sge; +volatile struct mlx4_wqe_data_seg *scat = &(*rxq->wqes)[i];struct rte_mbuf *buf =rte_pktmbuf_alloc (rxq->mp);if (buf ==NULL ) {
@@ -98,37 +97,35 @@ mlx4_rxq_alloc_elts(struct rxq *rxq, unsigned int elts_n)ERROR ("%p: empty mbuf pool" , (void *)rxq); goto error; } - elt->buf = buf; - wr->next = &(*elts)[(i +1 )].wr; - wr->sg_list = sge; - wr->num_sge =1 ;/* Headroom is reserved by rte_pktmbuf_alloc(). */ assert (buf->data_off ==RTE_PKTMBUF_HEADROOM );/* Buffer is supposed to be empty. */ assert (rte_pktmbuf_data_len (buf) ==0 );assert (rte_pktmbuf_pkt_len (buf) ==0 ); -/* sge->addr must be able to store a pointer. */ -assert (sizeof (sge->addr) >=sizeof (uintptr_t )); -/* SGE keeps its headroom. */ - sge->addr = (uintptr_t ) - ((uint8_t *)buf->buf_addr +RTE_PKTMBUF_HEADROOM ); - sge->length = (buf->buf_len -RTE_PKTMBUF_HEADROOM ); - sge->lkey = rxq->mr->lkey; -/* Redundant check for tailroom. */ -assert (sge->length ==rte_pktmbuf_tailroom (buf)); +/* Only the first segment keeps headroom. */ +if (i % sges_n) + buf->data_off =0 ; + buf->port = rxq->port_id; + buf->data_len =rte_pktmbuf_tailroom (buf); + buf->pkt_len =rte_pktmbuf_tailroom (buf); + buf->nb_segs =1 ; + *scat = (struct mlx4_wqe_data_seg ){ + .addr =rte_cpu_to_be_64 (rte_pktmbuf_mtod (buf, + uintptr_t)), + .byte_count =rte_cpu_to_be_32 (buf->data_len), + .lkey =rte_cpu_to_be_32 (rxq->mr->lkey), + }; + (*elts)[i] = buf; } -/* The last WR pointer must be NULL. */ - (*elts)[(i -1 )].wr.next =NULL ; -DEBUG ("%p: allocated and configured %u single-segment WRs" , - (void *)rxq, elts_n); - rxq->elts_n = elts_n; - rxq->elts_head =0 ; +DEBUG ("%p: allocated and configured %u segments (max %u packets)" , + (void *)rxq, elts_n, elts_n >> rxq->sges_n); + rxq->elts_n =log2above (elts_n); rxq->elts = elts;return 0 ; error:if (elts !=NULL ) {for (i =0 ; (i !=RTE_DIM (*elts)); ++i) -rte_pktmbuf_free_seg ((*elts)[i].buf); +rte_pktmbuf_free_seg ((*rxq->elts)[i]);rte_free (elts); }DEBUG ("%p: failed, freed everything" , (void *)rxq);
@@ -146,17 +143,16 @@ static void mlx4_rxq_free_elts(struct rxq *rxq) {unsigned int i; -unsigned int elts_n = rxq->elts_n; -struct rxq_elt (*elts)[elts_n] = rxq->elts; -DEBUG ("%p: freeing WRs" , (void *)rxq); +if (rxq->elts ==NULL ) +return ; +DEBUG ("%p: freeing Rx queue elements" , (void *)rxq); +for (i =0 ; i != (1u << rxq->elts_n); ++i) +if ((*rxq->elts)[i] !=NULL ) +rte_pktmbuf_free_seg ((*rxq->elts)[i]); +rte_free (rxq->elts); rxq->elts_n =0 ; rxq->elts =NULL ; -if (elts ==NULL ) -return ; -for (i =0 ; (i !=RTE_DIM (*elts)); ++i) -rte_pktmbuf_free_seg ((*elts)[i].buf); -rte_free (elts); }/**
@@ -193,12 +189,15 @@ mlx4_rxq_cleanup(struct rxq *rxq)* Completion queue to associate with QP. * @param desc * Number of descriptors in QP (hint only). +* @param sges_n +* Maximum number of segments per packet. * * @return * QP pointer or NULL in case of error and rte_errno is set. */ static struct ibv_qp * -mlx4_rxq_setup_qp (struct priv *priv,struct ibv_cq *cq,uint16_t desc) +mlx4_rxq_setup_qp (struct priv *priv,struct ibv_cq *cq,uint16_t desc, +uint32_t sges_n) {struct ibv_qp *qp;struct ibv_qp_init_attr attr = {
@@ -211,8 +210,8 @@ mlx4_rxq_setup_qp(struct priv *priv, struct ibv_cq *cq, uint16_t desc) .max_recv_wr = ((priv->device_attr.max_qp_wr < desc) ? priv->device_attr.max_qp_wr : desc), -/* Max number of scatter/gather elements in a WR. */ - .max_recv_sge = 1, +/* Maximum number of segments per packet. */ + .max_recv_sge = sges_n, }, .qp_type = IBV_QPT_RAW_PACKET, };
@@ -248,13 +247,15 @@ mlx4_rxq_setup(struct rte_eth_dev *dev, struct rxq *rxq, uint16_t desc, struct rte_mempool *mp) {struct priv *priv = dev->data->dev_private; +struct mlx4dv_obj mlxdv; +struct mlx4dv_qp dv_qp; +struct mlx4dv_cq dv_cq;struct rxq tmpl = { .priv = priv, .mp = mp, .socket = socket };struct ibv_qp_attr mod; -struct ibv_recv_wr *bad_wr;unsigned int mb_len;int ret;
@@ -269,11 +270,31 @@ mlx4_rxq_setup(struct rte_eth_dev *dev, struct rxq *rxq, uint16_t desc,assert (mb_len >=RTE_PKTMBUF_HEADROOM );if (dev->data->dev_conf.rxmode.max_rx_pkt_len <= (mb_len -RTE_PKTMBUF_HEADROOM )) { - ; + tmpl.sges_n =0 ; }else if (dev->data->dev_conf.rxmode.enable_scatter) { -WARN ("%p: scattered mode has been requested but is" -" not supported, this may lead to packet loss" , - (void *)dev); +uint32_t size = +RTE_PKTMBUF_HEADROOM + + dev->data->dev_conf.rxmode.max_rx_pkt_len; +uint32_t sges_n; + +/* +* Determine the number of SGEs needed for a full packet +* and round it to the next power of two. +*/ + sges_n =log2above ((size / mb_len) + !!(size % mb_len)); + tmpl.sges_n = sges_n; +/* Make sure sges_n did not overflow. */ + size = mb_len * (1 << tmpl.sges_n); + size -=RTE_PKTMBUF_HEADROOM ; +if (size < dev->data->dev_conf.rxmode.max_rx_pkt_len) { + rte_errno =EOVERFLOW ; +ERROR ("%p: too many SGEs (%u) needed to handle" +" requested maximum packet size %u" , + (void *)dev, +1 << sges_n, + dev->data->dev_conf.rxmode.max_rx_pkt_len); + goto error; + } }else {WARN ("%p: the requested maximum Rx packet size (%u) is" " larger than a single mbuf (%u) and scattered"
@@ -282,6 +303,17 @@ mlx4_rxq_setup(struct rte_eth_dev *dev, struct rxq *rxq, uint16_t desc, dev->data->dev_conf.rxmode.max_rx_pkt_len, mb_len - RTE_PKTMBUF_HEADROOM); } +DEBUG ("%p: maximum number of segments per packet: %u" , + (void *)dev,1 << tmpl.sges_n); +if (desc % (1 << tmpl.sges_n)) { + rte_errno =EINVAL ; +ERROR ("%p: number of RX queue descriptors (%u) is not a" +" multiple of maximum segments per packet (%u)" , + (void *)dev, + desc, +1 << tmpl.sges_n); + goto error; + }/* Use the entire Rx mempool as the memory region. */ tmpl.mr =mlx4_mp2mr (priv->pd, mp);if (tmpl.mr ==NULL ) {
@@ -306,7 +338,8 @@ mlx4_rxq_setup(struct rte_eth_dev *dev, struct rxq *rxq, uint16_t desc, goto error; } } - tmpl.cq =ibv_create_cq (priv->ctx, desc,NULL , tmpl.channel,0 ); + tmpl.cq =ibv_create_cq (priv->ctx, desc >> tmpl.sges_n,NULL , + tmpl.channel,0 );if (tmpl.cq ==NULL ) { rte_errno =ENOMEM ; ERROR("%p: CQ creation failure: %s",
@@ -317,7 +350,8 @@ mlx4_rxq_setup(struct rte_eth_dev *dev, struct rxq *rxq, uint16_t desc, priv->device_attr.max_qp_wr);DEBUG ("priv->device_attr.max_sge is %d" , priv->device_attr.max_sge); - tmpl.qp =mlx4_rxq_setup_qp (priv, tmpl.cq, desc); + tmpl.qp =mlx4_rxq_setup_qp (priv, tmpl.cq, desc >> tmpl.sges_n, +1 << tmpl.sges_n);if (tmpl.qp ==NULL ) {ERROR ("%p: QP creation failure: %s" , (void *)dev,strerror (rte_errno));
@@ -336,21 +370,6 @@ mlx4_rxq_setup(struct rte_eth_dev *dev, struct rxq *rxq, uint16_t desc, (void *)dev, strerror(rte_errno)); goto error; } - ret =mlx4_rxq_alloc_elts (&tmpl, desc); -if (ret) { -ERROR ("%p: RXQ allocation failed: %s" , - (void *)dev,strerror (rte_errno)); - goto error; - } - ret =ibv_post_recv (tmpl.qp, &(*tmpl.elts)[0 ].wr, &bad_wr); -if (ret) { - rte_errno = ret; -ERROR ("%p: ibv_post_recv() failed for WR %p: %s" , - (void *)dev, - (void *)bad_wr, -strerror (rte_errno)); - goto error; - } mod = (struct ibv_qp_attr ){ .qp_state =IBV_QPS_RTR };
@@ -361,14 +380,43 @@ mlx4_rxq_setup(struct rte_eth_dev *dev, struct rxq *rxq, uint16_t desc, (void *)dev, strerror(rte_errno)); goto error; } +/* Retrieve device queue information. */ + mlxdv.cq.in = tmpl.cq; + mlxdv.cq.out = &dv_cq; + mlxdv.qp.in = tmpl.qp; + mlxdv.qp.out = &dv_qp; + ret =mlx4dv_init_obj (&mlxdv,MLX4DV_OBJ_QP |MLX4DV_OBJ_CQ ); +if (ret) { +ERROR ("%p: failed to obtain device information" , (void *)dev); + goto error; + } + tmpl.wqes = + (volatile struct mlx4_wqe_data_seg (*)[]) + ((uintptr_t )dv_qp.buf.buf + dv_qp.rq.offset); + tmpl.rq_db = dv_qp.rdb; + tmpl.rq_ci =0 ; + tmpl.mcq.buf = dv_cq.buf.buf; + tmpl.mcq.cqe_cnt = dv_cq.cqe_cnt; + tmpl.mcq.set_ci_db = dv_cq.set_ci_db; + tmpl.mcq.cqe_64 = (dv_cq.cqe_size &64 ) ?1 :0 ;/* Save port ID. */ tmpl.port_id = dev->data->port_id;DEBUG ("%p: RTE port ID: %u" , (void *)rxq, tmpl.port_id); + ret =mlx4_rxq_alloc_elts (&tmpl, desc); +if (ret) { +ERROR ("%p: RXQ allocation failed: %s" , + (void *)dev,strerror (rte_errno)); + goto error; + }/* Clean up rxq in case we're reinitializing it. */ DEBUG ("%p: cleaning-up old rxq just in case" , (void *)rxq);mlx4_rxq_cleanup (rxq); *rxq = tmpl;DEBUG ("%p: rxq updated with %p" , (void *)rxq, (void *)&tmpl); +/* Update doorbell counter. */ + rxq->rq_ci = desc >> rxq->sges_n; +rte_wmb (); + *rxq->rq_db =rte_cpu_to_be_32 (rxq->rq_ci);return 0 ; error: ret = rte_errno;
@@ -406,6 +454,12 @@ mlx4_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,struct rxq *rxq = dev->data->rx_queues[idx];int ret; +if (!rte_is_power_of_2 (desc)) { + desc =1 <<log2above (desc); +WARN ("%p: increased number of descriptors in RX queue %u" +" to the next power of two (%d)" , + (void *)dev, idx, desc); + }DEBUG ("%p: configuring queue %u for %u descriptors" , (void *)dev, idx, desc);if (idx >= dev->data->nb_rx_queues) {
drivers/net/mlx4/mlx4_rxtx.c +128 -98
249 lines not on this page · raw message
drivers/net/mlx4/mlx4_rxtx.h +8 -11
@@ -62,13 +62,6 @@ struct mlx4_rxq_stats {uint64_t rx_nombuf;/**< Total of Rx mbuf allocation failures. */ }; -/** Rx element. */ -struct rxq_elt { -struct ibv_recv_wr wr;/**< Work request. */ -struct ibv_sge sge;/**< Scatter/gather element. */ -struct rte_mbuf *buf;/**< Buffer. */ -}; -/** Rx queue descriptor. */ struct rxq {struct priv *priv;/**< Back pointer to private data. */
@@ -77,10 +70,14 @@ struct rxq {struct ibv_cq *cq;/**< Completion queue. */ struct ibv_qp *qp;/**< Queue pair. */ struct ibv_comp_channel *channel;/**< Rx completion channel. */ -unsigned int port_id;/**< Port ID for incoming packets. */ -unsigned int elts_n;/**< (*elts)[] length. */ -unsigned int elts_head;/**< Current index in (*elts)[]. */ -struct rxq_elt (*elts)[];/**< Rx elements. */ +uint16_t rq_ci;/**< Saved RQ consumer index. */ +uint16_t port_id;/**< Port ID for incoming packets. */ +uint16_t sges_n;/**< Number of segments per packet (log2 value). */ +uint16_t elts_n;/**< Mbuf queue size (log2 value). */ +struct rte_mbuf *(*elts)[];/**< Rx elements. */ +volatile struct mlx4_wqe_data_seg (*wqes)[];/**< HW queue entries. */ +volatile uint32_t *rq_db;/**< RQ doorbell record. */ +struct mlx4_cq mcq;/**< Info for directly manipulating the CQ. */ struct mlx4_rxq_stats stats;/**< Rx queue counters. */ unsigned int socket;/**< CPU socket ID for allocations. */ };
drivers/net/mlx4/mlx4_utils.h +20 -0
@@ -108,4 +108,24 @@ pmd_drv_log_basename(const char *s)int mlx4_fd_set_non_blocking (int fd); +/** +* Return nearest power of two above input value. +* +* @param v +* Input value. +* +* @return +* Nearest power of two above input value. +*/ +static inline unsigned int +log2above (unsigned int v) +{ +unsigned int l; +unsigned int r; + +for (l =0 , r =0 ; (v >>1 ); ++l, v >>=1 ) + r |= (v &1 ); +return l + r; +} +#endif /* MLX4_UTILS_H_ */
Signature · 1 line
2.1.4
PATCH v3 3/6 net/mlx4: restore Tx gather support
In reply to Adrien MazarguilFrom: Moti Haimovsky <[email protected]>
This patch adds support for transmitting packets spanning over multiple buffers.
In this patch we also take into consideration the amount of entries a packet occupies in the TxQ when setting the report-completion flag of the chip.
--- drivers/net/mlx4/mlx4_rxtx.c | 197 ++++++++++++++++++++++---------------- drivers/net/mlx4/mlx4_rxtx.h | 6 +- drivers/net/mlx4/mlx4_txq.c | 12 ++- 3 files changed, 127 insertions(+), 88 deletions(-)
drivers/net/mlx4/mlx4_rxtx.c +113 -84
@@ -63,6 +63,15 @@#include "mlx4_utils.h" /** +* Pointer-value pair structure used in tx_post_send for saving the first +* DWORD (32 byte) of a TXBB. +*/ +struct pv { +struct mlx4_wqe_data_seg *dseg; +uint32_t val; +}; + +/** * Stamp a WQE so it won't be reused by the HW. * * Routine is used when freeing WQE used by the chip or when failing
@@ -291,24 +300,28 @@ mlx4_txq_mp2mr(struct txq *txq, struct rte_mempool *mp)* Target Tx queue. * @param pkt * Packet to transmit. -* @param send_flags -* @p MLX4_WQE_CTRL_CQ_UPDATE to request completion on this packet. * * @return * 0 on success, negative errno value otherwise and rte_errno is set. */ static inline int -mlx4_post_send (struct txq *txq,struct rte_mbuf *pkt,uint32_t send_flags) +mlx4_post_send (struct txq *txq,struct rte_mbuf *pkt) {struct mlx4_wqe_ctrl_seg *ctrl;struct mlx4_wqe_data_seg *dseg;struct mlx4_sq *sq = &txq->msq; +struct rte_mbuf *buf;uint32_t head_idx = sq->head & sq->txbb_cnt_mask;uint32_t lkey;uintptr_t addr; +uint32_t srcrb_flags; +uint32_t owner_opcode =MLX4_OPCODE_SEND ; +uint32_t byte_count;int wqe_real_size;int nr_txbbs;int rc; +struct pv *pv = (struct pv *)txq->bounce_buf; +int pv_counter =0 ;/* Calculate the needed work queue entry size for this packet. */ wqe_real_size = sizeof(struct mlx4_wqe_ctrl_seg) +
@@ -324,56 +337,81 @@ mlx4_post_send(struct txq *txq, struct rte_mbuf *pkt, uint32_t send_flags) rc =ENOSPC ; goto err; } -/* Get the control and single-data entries of the WQE. */ +/* Get the control and data entries of the WQE. */ ctrl = (struct mlx4_wqe_ctrl_seg *)mlx4_get_send_wqe (sq, head_idx); dseg = (struct mlx4_wqe_data_seg *)((uintptr_t )ctrl +sizeof (struct mlx4_wqe_ctrl_seg )); -/* Fill the data segment with buffer information. */ - addr =rte_pktmbuf_mtod (pkt, uintptr_t); -rte_prefetch0 ((volatile void *)addr); - dseg->addr =rte_cpu_to_be_64 (addr); -/* Memory region key for this memory pool. */ - lkey =mlx4_txq_mp2mr (txq,mlx4_txq_mb2mp (pkt)); -if (unlikely (lkey == (uint32_t )-1 )) { -/* MR does not exist. */ -DEBUG ("%p: unable to get MP <-> MR association" , (void *)txq); +/* Fill the data segments with buffer information. */ +for (buf = pkt; buf !=NULL ; buf = buf->next, dseg++) { + addr =rte_pktmbuf_mtod (buf, uintptr_t); +rte_prefetch0 ((volatile void *)addr); +/* Handle WQE wraparound. */ +if (unlikely (dseg >= (struct mlx4_wqe_data_seg *)sq->eob)) + dseg = (struct mlx4_wqe_data_seg *)sq->buf; + dseg->addr =rte_cpu_to_be_64 (addr); +/* Memory region key for this memory pool. */ + lkey =mlx4_txq_mp2mr (txq,mlx4_txq_mb2mp (buf)); +if (unlikely (lkey == (uint32_t )-1 )) { +/* MR does not exist. */ +DEBUG ("%p: unable to get MP <-> MR association" , + (void *)txq); +/* +* Restamp entry in case of failure. +* Make sure that size is written correctly +* Note that we give ownership to the SW, not the HW. +*/ + ctrl->fence_size = (wqe_real_size >>4 ) &0x3f ; +mlx4_txq_stamp_freed_wqe (sq, head_idx, + (sq->head & sq->txbb_cnt) ?0 :1 ); + rc =EFAULT ; + goto err; + } + dseg->lkey =rte_cpu_to_be_32 (lkey); +if (likely (buf->data_len)) { + byte_count =rte_cpu_to_be_32 (buf->data_len); + }else { +/* +* Zero length segment is treated as inline segment +* with zero data. +*/ + byte_count =RTE_BE32 (0x80000000 ); + }/* -* Restamp entry in case of failure, make sure that size is -* written correctly. -* Note that we give ownership to the SW, not the HW. +* If the data segment is not at the beginning of a +* Tx basic block (TXBB) then write the byte count, +* else postpone the writing to just before updating the +* control segment. */ - ctrl->fence_size = (wqe_real_size >>4 ) &0x3f ; -mlx4_txq_stamp_freed_wqe (sq, head_idx, - (sq->head & sq->txbb_cnt) ?0 :1 ); - rc =EFAULT ; - goto err; +if ((uintptr_t )dseg & (uintptr_t )(MLX4_TXBB_SIZE -1 )) { +/* +* Need a barrier here before writing the byte_count +* fields to make sure that all the data is visible +* before the byte_count field is set. +* Otherwise, if the segment begins a new cacheline, +* the HCA prefetcher could grab the 64-byte chunk and +* get a valid (!= 0xffffffff) byte count but stale +* data, and end up sending the wrong data. +*/ +rte_io_wmb (); + dseg->byte_count = byte_count; + }else { +/* +* This data segment starts at the beginning of a new +* TXBB, so we need to postpone its byte_count writing +* for later. +*/ + pv[pv_counter].dseg = dseg; + pv[pv_counter++].val = byte_count; + } } - dseg->lkey =rte_cpu_to_be_32 (lkey); -/* -* Need a barrier here before writing the byte_count field to -* make sure that all the data is visible before the -* byte_count field is set. Otherwise, if the segment begins -* a new cache line, the HCA prefetcher could grab the 64-byte -* chunk and get a valid (!= 0xffffffff) byte count but -* stale data, and end up sending the wrong data. -*/ -rte_io_wmb (); -if (likely (pkt->data_len)) - dseg->byte_count =rte_cpu_to_be_32 (pkt->data_len); -else -/* -* Zero length segment is treated as inline segment -* with zero data. -*/ - dseg->byte_count =RTE_BE32 (0x80000000 ); -/* -* Fill the control parameters for this packet. -* For raw Ethernet, the SOLICIT flag is used to indicate that no ICRC -* should be calculated. -*/ - ctrl->srcrb_flags = -rte_cpu_to_be_32 (MLX4_WQE_CTRL_SOLICIT | - (send_flags &MLX4_WQE_CTRL_CQ_UPDATE )); +/* Write the first DWORD of each TXBB save earlier. */ +if (pv_counter) { +/* Need a barrier here before writing the byte_count. */ +rte_io_wmb (); +for (--pv_counter; pv_counter >=0 ; pv_counter--) + pv[pv_counter].dseg->byte_count = pv[pv_counter].val; + } +/* Fill the control parameters for this packet. */ ctrl->fence_size = (wqe_real_size >>4 ) &0x3f ;/* * The caller should prepare "imm" in advance in order to support
@@ -382,14 +420,27 @@ mlx4_post_send(struct txq *txq, struct rte_mbuf *pkt, uint32_t send_flags)*/ ctrl->imm =0 ;/* -* Make sure descriptor is fully written before setting ownership -* bit (because HW can start executing as soon as we do). +* For raw Ethernet, the SOLICIT flag is used to indicate that no ICRC +* should be calculated. +*/ + txq->elts_comp_cd -= nr_txbbs; +if (unlikely (txq->elts_comp_cd <=0 )) { + txq->elts_comp_cd = txq->elts_comp_cd_init; + srcrb_flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT | +MLX4_WQE_CTRL_CQ_UPDATE ); + }else { + srcrb_flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT ); + } + ctrl->srcrb_flags = srcrb_flags; +/* +* Make sure descriptor is fully written before +* setting ownership bit (because HW can start +* executing as soon as we do). */ rte_wmb (); - ctrl->owner_opcode = -rte_cpu_to_be_32 (MLX4_OPCODE_SEND | - ((sq->head & sq->txbb_cnt) ? -MLX4_BIT_WQE_OWN :0 )); + ctrl->owner_opcode =rte_cpu_to_be_32 (owner_opcode | + ((sq->head & sq->txbb_cnt) ? +MLX4_BIT_WQE_OWN :0 )); sq->head += nr_txbbs;return 0 ; err:
@@ -416,14 +467,13 @@ mlx4_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)struct txq *txq = (struct txq *)dpdk_txq;unsigned int elts_head = txq->elts_head;const unsigned int elts_n = txq->elts_n; -unsigned int elts_comp_cd = txq->elts_comp_cd;unsigned int elts_comp =0 ;unsigned int bytes_sent =0 ;unsigned int i;unsigned int max;int err; -assert (elts_comp_cd !=0 ); +assert (txq->elts_comp_cd !=0 );mlx4_txq_complete (txq); max = (elts_n - (elts_head - txq->elts_tail));if (max > elts_n)
@@ -442,8 +492,6 @@ mlx4_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n) (((elts_head +1 ) == elts_n) ?0 : elts_head +1 );struct txq_elt *elt_next = &(*txq->elts)[elts_head_next];struct txq_elt *elt = &(*txq->elts)[elts_head]; -unsigned int segs = buf->nb_segs; -uint32_t send_flags =0 ;/* Clean up old buffer. */ if (likely (elt->buf !=NULL )) {
@@ -461,34 +509,16 @@ mlx4_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n) tmp = next; }while (tmp !=NULL ); } -/* Request Tx completion. */ -if (unlikely (--elts_comp_cd ==0 )) { - elts_comp_cd = txq->elts_comp_cd_init; - ++elts_comp; - send_flags |=MLX4_WQE_CTRL_CQ_UPDATE ; - } -if (likely (segs ==1 )) { -/* Update element. */ - elt->buf = buf; -RTE_MBUF_PREFETCH_TO_FREE (elt_next->buf); -/* Post the packet for sending. */ - err =mlx4_post_send (txq, buf, send_flags); -if (unlikely (err)) { -if (unlikely (send_flags & -MLX4_WQE_CTRL_CQ_UPDATE )) { - elts_comp_cd =1 ; - --elts_comp; - } - elt->buf =NULL ; - goto stop; - } - elt->buf = buf; - bytes_sent += buf->pkt_len; - }else { - err = -EINVAL ; - rte_errno = -err; +RTE_MBUF_PREFETCH_TO_FREE (elt_next->buf); +/* Post the packet for sending. */ + err =mlx4_post_send (txq, buf); +if (unlikely (err)) { + elt->buf =NULL ; goto stop; } + elt->buf = buf; + bytes_sent += buf->pkt_len; + ++elts_comp; elts_head = elts_head_next; } stop:
@@ -504,7 +534,6 @@ mlx4_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)rte_write32 (txq->msq.doorbell_qpn, txq->msq.db); txq->elts_head = elts_head; txq->elts_comp += elts_comp; - txq->elts_comp_cd = elts_comp_cd;return i; }
drivers/net/mlx4/mlx4_rxtx.h +4 -2
@@ -101,13 +101,15 @@ struct txq {struct mlx4_cq mcq;/**< Info for directly manipulating the CQ. */ unsigned int elts_head;/**< Current index in (*elts)[]. */ unsigned int elts_tail;/**< First element awaiting completion. */ -unsigned int elts_comp;/**< Number of completion requests. */ -unsigned int elts_comp_cd;/**< Countdown for next completion. */ +unsigned int elts_comp;/**< Number of packets awaiting completion. */ +int elts_comp_cd;/**< Countdown for next completion. */ unsigned int elts_comp_cd_init;/**< Initial value for countdown. */ unsigned int elts_n;/**< (*elts)[] length. */ struct txq_elt (*elts)[];/**< Tx elements. */ struct mlx4_txq_stats stats;/**< Tx queue counters. */ uint32_t max_inline;/**< Max inline send size. */ +uint8_t *bounce_buf; +/**< Memory used for storing the first DWORD of data TXBBs. */ struct {const struct rte_mempool *mp;/**< Cached memory pool. */ struct ibv_mr *mr;/**< Memory region (for mp). */
drivers/net/mlx4/mlx4_txq.c +10 -2
@@ -83,8 +83,13 @@ mlx4_txq_alloc_elts(struct txq *txq, unsigned int elts_n)rte_calloc_socket ("TXQ" ,1 ,sizeof (*elts),0 , txq->socket);int ret =0 ; -if (elts ==NULL ) { -ERROR ("%p: can't allocate packets array" , (void *)txq); +/* Allocate bounce buffer. */ + txq->bounce_buf =rte_zmalloc_socket ("TXQ" , +MLX4_MAX_WQE_SIZE , +RTE_CACHE_LINE_MIN_SIZE , + txq->socket); +if (!elts || !txq->bounce_buf) { +ERROR ("%p: can't allocate TXQ memory" , (void *)txq); ret =ENOMEM ; goto error; }
@@ -110,6 +115,8 @@ mlx4_txq_alloc_elts(struct txq *txq, unsigned int elts_n)assert (ret ==0 );return 0 ; error: +rte_free (txq->bounce_buf); + txq->bounce_buf =NULL ;rte_free (elts);DEBUG ("%p: failed, freed everything" , (void *)txq);assert (ret >0 );
@@ -175,6 +182,7 @@ mlx4_txq_cleanup(struct txq *txq)claim_zero (ibv_destroy_qp (txq->qp));if (txq->cq !=NULL )claim_zero (ibv_destroy_cq (txq->cq)); +rte_free (txq->bounce_buf);for (i =0 ; (i !=RTE_DIM (txq->mp2mr)); ++i) {if (txq->mp2mr[i].mp ==NULL )break ;
Signature · 1 line
2.1.4
PATCH v3 4/6 net/mlx4: restore Tx checksum offloads
In reply to Adrien MazarguilFrom: Moti Haimovsky <[email protected]>
This patch adds hardware offloading support for IPv4, UDP and TCP checksum calculation, including inner/outer checksums on supported tunnel types.
--- drivers/net/mlx4/mlx4.c | 11 +++++++++++ drivers/net/mlx4/mlx4.h | 2 ++ drivers/net/mlx4/mlx4_ethdev.c | 6 ++++++ drivers/net/mlx4/mlx4_prm.h | 2 ++ drivers/net/mlx4/mlx4_rxtx.c | 19 +++++++++++++++++++ drivers/net/mlx4/mlx4_rxtx.h | 2 ++ drivers/net/mlx4/mlx4_txq.c | 2 ++ 7 files changed, 44 insertions(+)
drivers/net/mlx4/mlx4.c +11 -0
@@ -529,6 +529,17 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) priv->pd = pd; priv->mtu =ETHER_MTU ; priv->vf = vf; + priv->hw_csum = !!(device_attr.device_cap_flags & +IBV_DEVICE_RAW_IP_CSUM ); +DEBUG ("checksum offloading is %ssupported" , + (priv->hw_csum ?"" :"not " )); +/* Only ConnectX-3 Pro supports tunneling. */ + priv->hw_csum_l2tun = + priv->hw_csum && + (device_attr.vendor_part_id == +PCI_DEVICE_ID_MELLANOX_CONNECTX3PRO ); +DEBUG ("L2 tunnel checksum offloads are %ssupported" , + (priv->hw_csum_l2tun ?"" :"not " ));/* Configure the first MAC address by default. */ if (mlx4_get_mac (priv, &mac.addr_bytes)) { ERROR("cannot get MAC address, is mlx4_en loaded?"
drivers/net/mlx4/mlx4.h +2 -0
@@ -104,6 +104,8 @@ struct priv { unsigned int vf:1; /* This is a VF device. */ unsigned int intr_alarm:1; /* An interrupt alarm is scheduled. */ unsigned int isolated:1; /* Toggle isolated mode. */ + unsigned int hw_csum:1; /* Checksum offload is supported. */ + unsigned int hw_csum_l2tun:1; /* Checksum support for L2 tunnels. */struct rte_intr_handle intr_handle;/* Port interrupt handle. */ struct rte_flow_drop *flow_drop_queue;/* Flow drop queue. */ LIST_HEAD(mlx4_flows, rte_flow) flows;
drivers/net/mlx4/mlx4_ethdev.c +6 -0
@@ -553,6 +553,12 @@ mlx4_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) info->max_mac_addrs =1 ; info->rx_offload_capa =0 ; info->tx_offload_capa =0 ; +if (priv->hw_csum) + info->tx_offload_capa |= (DEV_TX_OFFLOAD_IPV4_CKSUM | +DEV_TX_OFFLOAD_UDP_CKSUM | +DEV_TX_OFFLOAD_TCP_CKSUM ); +if (priv->hw_csum_l2tun) + info->tx_offload_capa |=DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM ;if (mlx4_get_ifname (priv, &ifname) ==0 ) info->if_index =if_nametoindex (ifname); info->speed_capa =
drivers/net/mlx4/mlx4_prm.h +2 -0
@@ -64,6 +64,8 @@/* Work queue element (WQE) flags. */ #define MLX4_BIT_WQE_OWN 0x80000000 +#define MLX4_WQE_CTRL_IIP_HDR_CSUM (1 << 28) +#define MLX4_WQE_CTRL_IL4_HDR_CSUM (1 << 27)#define MLX4_SIZE_TO_TXBBS (size) \ (RTE_ALIGN((size), (MLX4_TXBB_SIZE)) >> (MLX4_TXBB_SHIFT))
drivers/net/mlx4/mlx4_rxtx.c +19 -0
@@ -431,6 +431,25 @@ mlx4_post_send(struct txq *txq, struct rte_mbuf *pkt) }else { srcrb_flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT ); } +/* Enable HW checksum offload if requested */ +if (txq->csum && + (pkt->ol_flags & + (PKT_TX_IP_CKSUM |PKT_TX_TCP_CKSUM |PKT_TX_UDP_CKSUM ))) { +const uint64_t is_tunneled = (pkt->ol_flags & + (PKT_TX_TUNNEL_GRE | +PKT_TX_TUNNEL_VXLAN )); + +if (is_tunneled && txq->csum_l2tun) { + owner_opcode |=MLX4_WQE_CTRL_IIP_HDR_CSUM | +MLX4_WQE_CTRL_IL4_HDR_CSUM ; +if (pkt->ol_flags &PKT_TX_OUTER_IP_CKSUM ) + srcrb_flags |= +RTE_BE32 (MLX4_WQE_CTRL_IP_HDR_CSUM ); + }else { + srcrb_flags |=RTE_BE32 (MLX4_WQE_CTRL_IP_HDR_CSUM | +MLX4_WQE_CTRL_TCP_UDP_CSUM ); + } + } ctrl->srcrb_flags = srcrb_flags;/* * Make sure descriptor is fully written before
drivers/net/mlx4/mlx4_rxtx.h +2 -0
@@ -108,6 +108,8 @@ struct txq {struct txq_elt (*elts)[];/**< Tx elements. */ struct mlx4_txq_stats stats;/**< Tx queue counters. */ uint32_t max_inline;/**< Max inline send size. */ + uint32_t csum:1; /**< Enable checksum offloading. */ + uint32_t csum_l2tun:1; /**< Same for L2 tunnels. */uint8_t *bounce_buf;/**< Memory used for storing the first DWORD of data TXBBs. */ struct {
drivers/net/mlx4/mlx4_txq.c +2 -0
@@ -338,6 +338,8 @@ mlx4_txq_setup(struct rte_eth_dev *dev, struct txq *txq, uint16_t desc, (void *)dev, strerror(rte_errno)); goto error; } + tmpl.csum = priv->hw_csum; + tmpl.csum_l2tun = priv->hw_csum_l2tun;DEBUG ("priv->device_attr.max_qp_wr is %d" , priv->device_attr.max_qp_wr); DEBUG("priv->device_attr.max_sge is %d",
Signature · 1 line
2.1.4
PATCH v3 5/6 net/mlx4: restore Rx offloads
In reply to Adrien MazarguilFrom: Moti Haimovsky <[email protected]>
This patch adds hardware offloading support for IPV4, UDP and TCP checksum verification, including inner/outer checksums on supported tunnel types.
It also restores packet type recognition support.
--- drivers/net/mlx4/mlx4_ethdev.c | 6 +- drivers/net/mlx4/mlx4_prm.h | 30 +++++++++ drivers/net/mlx4/mlx4_rxq.c | 5 ++ drivers/net/mlx4/mlx4_rxtx.c | 118 +++++++++++++++++++++++++++++++++++- drivers/net/mlx4/mlx4_rxtx.h | 2 + 5 files changed, 158 insertions(+), 3 deletions(-)
drivers/net/mlx4/mlx4_ethdev.c +5 -1
@@ -553,10 +553,14 @@ mlx4_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) info->max_mac_addrs =1 ; info->rx_offload_capa =0 ; info->tx_offload_capa =0 ; -if (priv->hw_csum) +if (priv->hw_csum) { info->tx_offload_capa |= (DEV_TX_OFFLOAD_IPV4_CKSUM |DEV_TX_OFFLOAD_UDP_CKSUM |DEV_TX_OFFLOAD_TCP_CKSUM ); + info->rx_offload_capa |= (DEV_RX_OFFLOAD_IPV4_CKSUM | +DEV_RX_OFFLOAD_UDP_CKSUM | +DEV_RX_OFFLOAD_TCP_CKSUM ); + }if (priv->hw_csum_l2tun) info->tx_offload_capa |=DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM ;if (mlx4_get_ifname (priv, &ifname) ==0 )
drivers/net/mlx4/mlx4_prm.h +30 -0
@@ -70,6 +70,14 @@#define MLX4_SIZE_TO_TXBBS (size) \ (RTE_ALIGN((size), (MLX4_TXBB_SIZE)) >> (MLX4_TXBB_SHIFT)) +/* CQE checksum flags. */ +enum { +MLX4_CQE_L2_TUNNEL_IPV4 = (int )(1u <<25 ), +MLX4_CQE_L2_TUNNEL_L4_CSUM = (int )(1u <<26 ), +MLX4_CQE_L2_TUNNEL = (int )(1u <<27 ), +MLX4_CQE_L2_TUNNEL_IPOK = (int )(1u <<31 ), +}; +/* Send queue information. */ struct mlx4_sq {uint8_t *buf;/**< SQ buffer. */
@@ -119,4 +127,26 @@ mlx4_get_cqe(struct mlx4_cq *cq, uint32_t index) (cq->cqe_64 << 5)); } +/** +* Transpose a flag in a value. +* +* @param val +* Input value. +* @param from +* Flag to retrieve from input value. +* @param to +* Flag to set in output value. +* +* @return +* Output value with transposed flag enabled if present on input. +*/ +static inline uint64_t +mlx4_transpose (uint64_t val,uint64_t from,uint64_t to) +{ +return (from >= to ? + (val & from) / (from / to) : + (val & from) * (to / from)); +} + +#endif /* MLX4_PRM_H_ */
drivers/net/mlx4/mlx4_rxq.c +5 -0
@@ -260,6 +260,11 @@ mlx4_rxq_setup(struct rte_eth_dev *dev, struct rxq *rxq, uint16_t desc,int ret; (void )conf;/* Thresholds configuration (ignored). */ +/* Toggle Rx checksum offload if hardware supports it. */ +if (priv->hw_csum) + tmpl.csum = !!dev->data->dev_conf.rxmode.hw_ip_checksum; +if (priv->hw_csum_l2tun) + tmpl.csum_l2tun = !!dev->data->dev_conf.rxmode.hw_ip_checksum; mb_len =rte_pktmbuf_data_room_size (mp);if (desc ==0 ) { rte_errno =EINVAL ;
drivers/net/mlx4/mlx4_rxtx.c +116 -2
130 lines not on this page · raw message
drivers/net/mlx4/mlx4_rxtx.h +2 -0
@@ -77,6 +77,8 @@ struct rxq {struct rte_mbuf *(*elts)[];/**< Rx elements. */ volatile struct mlx4_wqe_data_seg (*wqes)[];/**< HW queue entries. */ volatile uint32_t *rq_db;/**< RQ doorbell record. */ + uint32_t csum:1; /**< Enable checksum offloading. */ + uint32_t csum_l2tun:1; /**< Same for L2 tunnels. */struct mlx4_cq mcq;/**< Info for directly manipulating the CQ. */ struct mlx4_rxq_stats stats;/**< Rx queue counters. */ unsigned int socket;/**< CPU socket ID for allocations. */
Signature · 1 line
2.1.4
PATCH v3 6/6 net/mlx4: add loopback Tx from VF
In reply to Adrien MazarguilFrom: Moti Haimovsky <[email protected]>
This patch adds loopback functionality used when the chip is a VF in order to enable packet transmission between VFs and PF.
--- drivers/net/mlx4/mlx4_rxtx.c | 33 +++++++++++++++++++++------------ drivers/net/mlx4/mlx4_rxtx.h | 1 + drivers/net/mlx4/mlx4_txq.c | 2 ++ 3 files changed, 24 insertions(+), 12 deletions(-)
drivers/net/mlx4/mlx4_rxtx.c +21 -12
@@ -311,10 +311,13 @@ mlx4_post_send(struct txq *txq, struct rte_mbuf *pkt)struct mlx4_wqe_data_seg *dseg;struct mlx4_sq *sq = &txq->msq;struct rte_mbuf *buf; +union { +uint32_t flags; +uint16_t flags16[2 ]; + } srcrb;uint32_t head_idx = sq->head & sq->txbb_cnt_mask;uint32_t lkey;uintptr_t addr; -uint32_t srcrb_flags;uint32_t owner_opcode =MLX4_OPCODE_SEND ;uint32_t byte_count;int wqe_real_size;
@@ -414,22 +417,16 @@ mlx4_post_send(struct txq *txq, struct rte_mbuf *pkt)/* Fill the control parameters for this packet. */ ctrl->fence_size = (wqe_real_size >>4 ) &0x3f ;/* -* The caller should prepare "imm" in advance in order to support -* VF to VF communication (when the device is a virtual-function -* device (VF)). -*/ - ctrl->imm =0 ; -/* * For raw Ethernet, the SOLICIT flag is used to indicate that no ICRC * should be calculated. */ txq->elts_comp_cd -= nr_txbbs;if (unlikely (txq->elts_comp_cd <=0 )) { txq->elts_comp_cd = txq->elts_comp_cd_init; - srcrb_flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT | + srcrb.flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT |MLX4_WQE_CTRL_CQ_UPDATE ); }else { - srcrb_flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT ); + srcrb.flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT ); }/* Enable HW checksum offload if requested */ if (txq->csum &&
@@ -443,14 +440,26 @@ mlx4_post_send(struct txq *txq, struct rte_mbuf *pkt) owner_opcode |=MLX4_WQE_CTRL_IIP_HDR_CSUM |MLX4_WQE_CTRL_IL4_HDR_CSUM ;if (pkt->ol_flags &PKT_TX_OUTER_IP_CKSUM ) - srcrb_flags |= + srcrb.flags |=RTE_BE32 (MLX4_WQE_CTRL_IP_HDR_CSUM ); }else { - srcrb_flags |=RTE_BE32 (MLX4_WQE_CTRL_IP_HDR_CSUM | + srcrb.flags |=RTE_BE32 (MLX4_WQE_CTRL_IP_HDR_CSUM |MLX4_WQE_CTRL_TCP_UDP_CSUM ); } } - ctrl->srcrb_flags = srcrb_flags; +if (txq->lb) { +/* +* Copy destination MAC address to the WQE, this allows +* loopback in eSwitch, so that VFs and PF can communicate +* with each other. +*/ + srcrb.flags16[0] = *(rte_pktmbuf_mtod(pkt, uint16_t *)); + ctrl->imm = *(rte_pktmbuf_mtod_offset (pkt ,uint32_t *, + sizeof(uint16_t))); + }else { + ctrl->imm =0 ; + } + ctrl->srcrb_flags = srcrb.flags;/* * Make sure descriptor is fully written before * setting ownership bit (because HW can start
drivers/net/mlx4/mlx4_rxtx.h +1 -0
@@ -112,6 +112,7 @@ struct txq {uint32_t max_inline;/**< Max inline send size. */ uint32_t csum:1; /**< Enable checksum offloading. */ uint32_t csum_l2tun:1; /**< Same for L2 tunnels. */ + uint32_t lb:1; /**< Whether packets should be looped back by eSwitch. */uint8_t *bounce_buf;/**< Memory used for storing the first DWORD of data TXBBs. */ struct {
drivers/net/mlx4/mlx4_txq.c +2 -0
@@ -412,6 +412,8 @@ mlx4_txq_setup(struct rte_eth_dev *dev, struct txq *txq, uint16_t desc, (void *)dev, strerror(rte_errno)); goto error; } +/* Enable Tx loopback for VF devices. */ + tmpl.lb = !!(priv->vf);/* Clean up txq in case we're reinitializing it. */ DEBUG ("%p: cleaning-up old txq just in case" , (void *)txq);mlx4_txq_cleanup (txq);
Signature · 1 line
2.1.4
v4 cover new mlx4 datapath bypassing ibverbs
In reply to Adrien Mazarguilv4 (Ophir):
- Split "net/mlx4: restore Rx scatter support" commit from "net/mlx4:
restore full Rx support bypassing Verbs" commit
v3 (Adrien):
- Drop a few unrelated or unnecessary changes such as the removal of MLX4_PMD_TX_MP_CACHE.
- Move device checksum support detection code to its previous location.
- Fix include guard in mlx4_prm.h.
- Reorder #includes alphabetically.
- Replace MLX4_TRANSPOSE() macro with documented inline function.
- Remove extra spaces and blank lines.
- Use uint8_t * instead of char * for buffers.
- Replace mlx4_get_cqe() macro with a documented inline function.
- Replace several unsigned int with uint32_t.
- Add consistency to field names (sge_n => sges_n).
- Make mbuf size checks in RX queue setup function similar to mlx5.
- Update various comments.
- Fix indentation.
- Replace run-time endian conversion with static ones where possible.
- Reorder fields in struct rxq and struct txq for consistency, remove one level of unnecessary inner structures.
- Fix memory leak on Tx bounce buffer.
- Update commit logs.
- Fix remaining checkpatch warnings.
v2 (Matan):
Rearange patches.
Semantics.
Enhancements.
Fix compilation issues.
Moti Haimovsky (6):
net/mlx4: add simple Tx bypassing Verbs net/mlx4: restore full Rx support bypassing Verbs net/mlx4: restore Tx gather support net/mlx4: restore Tx checksum offloads net/mlx4: restore Rx offloads
net/mlx4: add loopback Tx from VF
Ophir Munk (1):
net/mlx4: restore Rx scatter support
drivers/net/mlx4/mlx4.c | 11 + drivers/net/mlx4/mlx4.h | 2 + drivers/net/mlx4/mlx4_ethdev.c | 10 + drivers/net/mlx4/mlx4_prm.h | 152 ++++++++ drivers/net/mlx4/mlx4_rxq.c | 179 ++++++---- drivers/net/mlx4/mlx4_rxtx.c | 768 ++++++++++++++++++++++++++++++----------- drivers/net/mlx4/mlx4_rxtx.h | 54 +-- drivers/net/mlx4/mlx4_txq.c | 67 +++- drivers/net/mlx4/mlx4_utils.h | 20 ++ mk/rte.app.mk | 2 +- 10 files changed, 975 insertions(+), 290 deletions(-) create mode 100644 drivers/net/mlx4/mlx4_prm.h
Signature · 1 line
1.8.3.1
PATCH v4 1/7 net/mlx4: add simple Tx bypassing Verbs
From: Moti Haimovsky <[email protected]>
Modify PMD to send single-buffer packets directly to the device bypassing the Verbs Tx post and poll routines.
--- drivers/net/mlx4/mlx4_prm.h | 120 +++++++++++++++ drivers/net/mlx4/mlx4_rxtx.c | 337 ++++++++++++++++++++++++++++++++----------- drivers/net/mlx4/mlx4_rxtx.h | 28 ++-- drivers/net/mlx4/mlx4_txq.c | 51 +++++++ mk/rte.app.mk | 2 +- 5 files changed, 436 insertions(+), 102 deletions(-) create mode 100644 drivers/net/mlx4/mlx4_prm.h
drivers/net/mlx4/mlx4_prm.h new file +120 -0
@@ -0,0 +1,120 @@ +/*- +* BSD LICENSE +* +* Copyright 2017 6WIND S.A. +* Copyright 2017 Mellanox +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of 6WIND S.A. nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef MLX4_PRM_H_ +#define MLX4_PRM_H_ + +#include <rte_atomic.h> +#include <rte_branch_prediction.h> +#include <rte_byteorder.h> + +/* Verbs headers do not support -pedantic. */ +#ifdef PEDANTIC +#pragma GCC diagnostic ignored "-Wpedantic" +#endif +#include <infiniband/mlx4dv.h> +#include <infiniband/verbs.h> +#ifdef PEDANTIC +#pragma GCC diagnostic error "-Wpedantic" +#endif + +/* ConnectX-3 Tx queue basic block. */ +#define MLX4_TXBB_SHIFT 6 +#define MLX4_TXBB_SIZE (1 << MLX4_TXBB_SHIFT) + +/* Typical TSO descriptor with 16 gather entries is 352 bytes. */ +#define MLX4_MAX_WQE_SIZE 512 +#define MLX4_MAX_WQE_TXBBS (MLX4_MAX_WQE_SIZE / MLX4_TXBB_SIZE) + +/* Send queue stamping/invalidating information. */ +#define MLX4_SQ_STAMP_STRIDE 64 +#define MLX4_SQ_STAMP_DWORDS (MLX4_SQ_STAMP_STRIDE / 4) +#define MLX4_SQ_STAMP_SHIFT 31 +#define MLX4_SQ_STAMP_VAL 0x7fffffff + +/* Work queue element (WQE) flags. */ +#define MLX4_BIT_WQE_OWN 0x80000000 + +#define MLX4_SIZE_TO_TXBBS (size) \ + (RTE_ALIGN((size), (MLX4_TXBB_SIZE)) >> (MLX4_TXBB_SHIFT)) + +/* Send queue information. */ +struct mlx4_sq { +uint8_t *buf;/**< SQ buffer. */ +uint8_t *eob;/**< End of SQ buffer */ +uint32_t head;/**< SQ head counter in units of TXBBS. */ +uint32_t tail;/**< SQ tail counter in units of TXBBS. */ +uint32_t txbb_cnt;/**< Num of WQEBB in the Q (should be ^2). */ +uint32_t txbb_cnt_mask;/**< txbbs_cnt mask (txbb_cnt is ^2). */ +uint32_t headroom_txbbs;/**< Num of txbbs that should be kept free. */ +uint32_t *db;/**< Pointer to the doorbell. */ +uint32_t doorbell_qpn;/**< qp number to write to the doorbell. */ +}; + +#define mlx4_get_send_wqe (sq, n) ((sq)->buf + ((n) * (MLX4_TXBB_SIZE))) + +/* Completion queue information. */ +struct mlx4_cq { +uint8_t *buf;/**< Pointer to the completion queue buffer. */ +uint32_t cqe_cnt;/**< Number of entries in the queue. */ +uint32_t cqe_64:1 ;/**< CQ entry size is 64 bytes. */ +uint32_t cons_index;/**< Last queue entry that was handled. */ +uint32_t *set_ci_db;/**< Pointer to the completion queue doorbell. */ +}; + +/** +* Retrieve a CQE entry from a CQ. +* +* cqe = cq->buf + cons_index * cqe_size + cqe_offset +* +* Where cqe_size is 32 or 64 bytes and cqe_offset is 0 or 32 (depending on +* cqe_size). +* +* @param cq +* CQ to retrieve entry from. +* @param index +* Entry index. +* +* @return +* Pointer to CQE entry. +*/ +static inline struct mlx4_cqe * +mlx4_get_cqe (struct mlx4_cq *cq,uint32_t index) +{ +return (struct mlx4_cqe *)(cq->buf + + ((index & (cq->cqe_cnt -1 )) << + (5 + cq->cqe_64)) + + (cq->cqe_64 <<5 )); +} + +#endif /* MLX4_PRM_H_ */
drivers/net/mlx4/mlx4_rxtx.c +249 -88
411 lines not on this page · raw message
drivers/net/mlx4/mlx4_rxtx.h +15 -13
@@ -40,6 +40,7 @@#ifdef PEDANTIC #pragma GCC diagnostic ignored "-Wpedantic"#endif +#include <infiniband/mlx4dv.h> #include <infiniband/verbs.h> #ifdef PEDANTIC #pragma GCC diagnostic error "-Wpedantic"
@@ -50,6 +51,7 @@#include <rte_mempool.h> #include "mlx4.h" +#include "mlx4_prm.h" /** Rx queue counters. */ struct mlx4_rxq_stats {
@@ -85,8 +87,6 @@ struct rxq {/** Tx element. */ struct txq_elt { -struct ibv_send_wr wr;/* Work request. */ -struct ibv_sge sge;/* Scatter/gather element. */ struct rte_mbuf *buf;/**< Buffer. */ };
@@ -100,24 +100,26 @@ struct mlx4_txq_stats {/** Tx queue descriptor. */ struct txq { -struct priv *priv;/**< Back pointer to private data. */ -struct { -const struct rte_mempool *mp;/**< Cached memory pool. */ -struct ibv_mr *mr;/**< Memory region (for mp). */ -uint32_t lkey;/**< mr->lkey copy. */ - } mp2mr[MLX4_PMD_TX_MP_CACHE ];/**< MP to MR translation table. */ -struct ibv_cq *cq;/**< Completion queue. */ -struct ibv_qp *qp;/**< Queue pair. */ -uint32_t max_inline;/**< Max inline send size. */ -unsigned int elts_n;/**< (*elts)[] length. */ -struct txq_elt (*elts)[];/**< Tx elements. */ +struct mlx4_sq msq;/**< Info for directly manipulating the SQ. */ +struct mlx4_cq mcq;/**< Info for directly manipulating the CQ. */ unsigned int elts_head;/**< Current index in (*elts)[]. */ unsigned int elts_tail;/**< First element awaiting completion. */ unsigned int elts_comp;/**< Number of completion requests. */ unsigned int elts_comp_cd;/**< Countdown for next completion. */ unsigned int elts_comp_cd_init;/**< Initial value for countdown. */ +unsigned int elts_n;/**< (*elts)[] length. */ +struct txq_elt (*elts)[];/**< Tx elements. */ struct mlx4_txq_stats stats;/**< Tx queue counters. */ +uint32_t max_inline;/**< Max inline send size. */ +struct { +const struct rte_mempool *mp;/**< Cached memory pool. */ +struct ibv_mr *mr;/**< Memory region (for mp). */ +uint32_t lkey;/**< mr->lkey copy. */ + } mp2mr[MLX4_PMD_TX_MP_CACHE ];/**< MP to MR translation table. */ +struct priv *priv;/**< Back pointer to private data. */ unsigned int socket;/**< CPU socket ID for allocations. */ +struct ibv_cq *cq;/**< Completion queue. */ +struct ibv_qp *qp;/**< Queue pair. */ };/* mlx4_rxq.c */
drivers/net/mlx4/mlx4_txq.c +51 -0
75 lines not on this page · raw message
mk/rte.app.mk +1 -1
@@ -133,7 +133,7 @@ ifeq ($(CONFIG_RTE_LIBRTE_KNI),y) _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_KNI) += -lrte_pmd_kni endif _LDLIBS-$(CONFIG_RTE_LIBRTE_LIO_PMD) += -lrte_pmd_lio -_LDLIBS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += -lrte_pmd_mlx4 -libverbs +_LDLIBS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += -lrte_pmd_mlx4 -libverbs -lmlx4 _LDLIBS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += -lrte_pmd_mlx5 -libverbs -lmlx5 _LDLIBS-$(CONFIG_RTE_LIBRTE_NFP_PMD) += -lrte_pmd_nfp _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += -lrte_pmd_null
Signature · 1 line
1.8.3.1
PATCH v4 2/7 net/mlx4: restore full Rx support bypassing Verbs
In reply to Ophir MunkFrom: Moti Haimovsky <[email protected]>
This patch adds support for accessing the hardware directly when handling Rx packets eliminating the need to use Verbs in the Rx data path.
The number of scatters is limited to one.
--- drivers/net/mlx4/mlx4_rxq.c | 110 +++++++++++---------- drivers/net/mlx4/mlx4_rxtx.c | 223 +++++++++++++++++++++++------------------- drivers/net/mlx4/mlx4_rxtx.h | 18 ++-- drivers/net/mlx4/mlx4_utils.h | 20 ++++ 4 files changed, 212 insertions(+), 159 deletions(-)
drivers/net/mlx4/mlx4_rxq.c +60 -50
@@ -51,6 +51,7 @@#pragma GCC diagnostic error "-Wpedantic"#endif +#include <rte_byteorder.h> #include <rte_common.h> #include <rte_errno.h> #include <rte_ethdev.h>
@@ -77,20 +78,17 @@ mlx4_rxq_alloc_elts(struct rxq *rxq, unsigned int elts_n) {unsigned int i; -struct rxq_elt (*elts)[elts_n] = -rte_calloc_socket ("RXQ elements" ,1 ,sizeof (*elts),0 , - rxq->socket); +struct rte_mbuf *(*elts)[elts_n] = +rte_calloc_socket ("RXQ" ,1 ,sizeof (*elts),0 , rxq->socket); +assert (rte_is_power_of_2 (elts_n));if (elts ==NULL ) { rte_errno =ENOMEM ;ERROR ("%p: can't allocate packets array" , (void *)rxq); goto error; } -/* For each WR (packet). */ for (i =0 ; (i != elts_n); ++i) { -struct rxq_elt *elt = &(*elts)[i]; -struct ibv_recv_wr *wr = &elt->wr; -struct ibv_sge *sge = &(*elts)[i].sge; +volatile struct mlx4_wqe_data_seg *scat = &(*rxq->wqes)[i];struct rte_mbuf *buf =rte_pktmbuf_alloc (rxq->mp);if (buf ==NULL ) {
@@ -98,37 +96,32 @@ERROR ("%p: empty mbuf pool" , (void *)rxq); goto error; } - elt->buf = buf; - wr->next = &(*elts)[(i +1 )].wr; - wr->sg_list = sge; - wr->num_sge =1 ;/* Headroom is reserved by rte_pktmbuf_alloc(). */ assert (buf->data_off ==RTE_PKTMBUF_HEADROOM );/* Buffer is supposed to be empty. */ assert (rte_pktmbuf_data_len (buf) ==0 );assert (rte_pktmbuf_pkt_len (buf) ==0 ); -/* sge->addr must be able to store a pointer. */ -assert (sizeof (sge->addr) >=sizeof (uintptr_t )); -/* SGE keeps its headroom. */ - sge->addr = (uintptr_t ) - ((uint8_t *)buf->buf_addr +RTE_PKTMBUF_HEADROOM ); - sge->length = (buf->buf_len -RTE_PKTMBUF_HEADROOM ); - sge->lkey = rxq->mr->lkey; -/* Redundant check for tailroom. */ -assert (sge->length ==rte_pktmbuf_tailroom (buf)); + buf->port = rxq->port_id; + buf->data_len =rte_pktmbuf_tailroom (buf); + buf->pkt_len =rte_pktmbuf_tailroom (buf); + buf->nb_segs =1 ; + *scat = (struct mlx4_wqe_data_seg ){ + .addr =rte_cpu_to_be_64 (rte_pktmbuf_mtod (buf, + uintptr_t)), + .byte_count =rte_cpu_to_be_32 (buf->data_len), + .lkey =rte_cpu_to_be_32 (rxq->mr->lkey), + }; + (*elts)[i] = buf; } -/* The last WR pointer must be NULL. */ - (*elts)[(i -1 )].wr.next =NULL ;DEBUG ("%p: allocated and configured %u single-segment WRs" , (void *)rxq, elts_n); - rxq->elts_n = elts_n; - rxq->elts_head =0 ; + rxq->elts_n =log2above (elts_n); rxq->elts = elts;return 0 ; error:if (elts !=NULL ) {for (i =0 ; (i !=RTE_DIM (*elts)); ++i) -rte_pktmbuf_free_seg ((*elts)[i].buf); +rte_pktmbuf_free_seg ((*rxq->elts)[i]);rte_free (elts); }DEBUG ("%p: failed, freed everything" , (void *)rxq);
@@ -146,17 +139,16 @@ mlx4_rxq_free_elts(struct rxq *rxq) {unsigned int i; -unsigned int elts_n = rxq->elts_n; -struct rxq_elt (*elts)[elts_n] = rxq->elts; -DEBUG ("%p: freeing WRs" , (void *)rxq); +if (rxq->elts ==NULL ) +return ; +DEBUG ("%p: freeing Rx queue elements" , (void *)rxq); +for (i =0 ; i != (1u << rxq->elts_n); ++i) +if ((*rxq->elts)[i] !=NULL ) +rte_pktmbuf_free_seg ((*rxq->elts)[i]); +rte_free (rxq->elts); rxq->elts_n =0 ; rxq->elts =NULL ; -if (elts ==NULL ) -return ; -for (i =0 ; (i !=RTE_DIM (*elts)); ++i) -rte_pktmbuf_free_seg ((*elts)[i].buf); -rte_free (elts); }/**
@@ -211,7 +203,7 @@ .max_recv_wr = ((priv->device_attr.max_qp_wr < desc) ? priv->device_attr.max_qp_wr : desc), -/* Max number of scatter/gather elements in a WR. */ +/* Maximum number of segments per packet. */ .max_recv_sge = 1, }, .qp_type = IBV_QPT_RAW_PACKET,
@@ -248,13 +240,15 @@ struct rte_mempool *mp) {struct priv *priv = dev->data->dev_private; +struct mlx4dv_obj mlxdv; +struct mlx4dv_qp dv_qp; +struct mlx4dv_cq dv_cq;struct rxq tmpl = { .priv = priv, .mp = mp, .socket = socket };struct ibv_qp_attr mod; -struct ibv_recv_wr *bad_wr;unsigned int mb_len;int ret;
@@ -336,21 +330,6 @@ (void *)dev, strerror(rte_errno)); goto error; } - ret =mlx4_rxq_alloc_elts (&tmpl, desc); -if (ret) { -ERROR ("%p: RXQ allocation failed: %s" , - (void *)dev,strerror (rte_errno)); - goto error; - } - ret =ibv_post_recv (tmpl.qp, &(*tmpl.elts)[0 ].wr, &bad_wr); -if (ret) { - rte_errno = ret; -ERROR ("%p: ibv_post_recv() failed for WR %p: %s" , - (void *)dev, - (void *)bad_wr, -strerror (rte_errno)); - goto error; - } mod = (struct ibv_qp_attr ){ .qp_state =IBV_QPS_RTR };
@@ -361,9 +340,34 @@ (void *)dev, strerror(rte_errno)); goto error; } +/* Retrieve device queue information. */ + mlxdv.cq.in = tmpl.cq; + mlxdv.cq.out = &dv_cq; + mlxdv.qp.in = tmpl.qp; + mlxdv.qp.out = &dv_qp; + ret =mlx4dv_init_obj (&mlxdv,MLX4DV_OBJ_QP |MLX4DV_OBJ_CQ ); +if (ret) { +ERROR ("%p: failed to obtain device information" , (void *)dev); + goto error; + } + tmpl.wqes = + (volatile struct mlx4_wqe_data_seg (*)[]) + ((uintptr_t )dv_qp.buf.buf + dv_qp.rq.offset); + tmpl.rq_db = dv_qp.rdb; + tmpl.rq_ci =0 ; + tmpl.mcq.buf = dv_cq.buf.buf; + tmpl.mcq.cqe_cnt = dv_cq.cqe_cnt; + tmpl.mcq.set_ci_db = dv_cq.set_ci_db; + tmpl.mcq.cqe_64 = (dv_cq.cqe_size &64 ) ?1 :0 ;/* Save port ID. */ tmpl.port_id = dev->data->port_id;DEBUG ("%p: RTE port ID: %u" , (void *)rxq, tmpl.port_id); + ret =mlx4_rxq_alloc_elts (&tmpl, desc); +if (ret) { +ERROR ("%p: RXQ allocation failed: %s" , + (void *)dev,strerror (rte_errno)); + goto error; + }/* Clean up rxq in case we're reinitializing it. */ DEBUG ("%p: cleaning-up old rxq just in case" , (void *)rxq);mlx4_rxq_cleanup (rxq);
@@ -406,6 +410,12 @@struct rxq *rxq = dev->data->rx_queues[idx];int ret; +if (!rte_is_power_of_2 (desc)) { + desc =1 <<log2above (desc); +WARN ("%p: increased number of descriptors in RX queue %u" +" to the next power of two (%d)" , + (void *)dev, idx, desc); + }DEBUG ("%p: configuring queue %u for %u descriptors" , (void *)dev, idx, desc);if (idx >= dev->data->nb_rx_queues) {
drivers/net/mlx4/mlx4_rxtx.c +125 -98
246 lines not on this page · raw message
drivers/net/mlx4/mlx4_rxtx.h +7 -11
@@ -62,13 +62,6 @@ struct mlx4_rxq_stats {uint64_t rx_nombuf;/**< Total of Rx mbuf allocation failures. */ }; -/** Rx element. */ -struct rxq_elt { -struct ibv_recv_wr wr;/**< Work request. */ -struct ibv_sge sge;/**< Scatter/gather element. */ -struct rte_mbuf *buf;/**< Buffer. */ -}; -/** Rx queue descriptor. */ struct rxq {struct priv *priv;/**< Back pointer to private data. */
@@ -77,10 +70,13 @@ struct rxq {struct ibv_cq *cq;/**< Completion queue. */ struct ibv_qp *qp;/**< Queue pair. */ struct ibv_comp_channel *channel;/**< Rx completion channel. */ -unsigned int port_id;/**< Port ID for incoming packets. */ -unsigned int elts_n;/**< (*elts)[] length. */ -unsigned int elts_head;/**< Current index in (*elts)[]. */ -struct rxq_elt (*elts)[];/**< Rx elements. */ +uint16_t rq_ci;/**< Saved RQ consumer index. */ +uint16_t port_id;/**< Port ID for incoming packets. */ +uint16_t elts_n;/**< Mbuf queue size (log2 value). */ +struct rte_mbuf *(*elts)[];/**< Rx elements. */ +volatile struct mlx4_wqe_data_seg (*wqes)[];/**< HW queue entries. */ +volatile uint32_t *rq_db;/**< RQ doorbell record. */ +struct mlx4_cq mcq;/**< Info for directly manipulating the CQ. */ struct mlx4_rxq_stats stats;/**< Rx queue counters. */ unsigned int socket;/**< CPU socket ID for allocations. */ };
drivers/net/mlx4/mlx4_utils.h +20 -0
@@ -108,4 +108,24 @@int mlx4_fd_set_non_blocking (int fd); +/** +* Return nearest power of two above input value. +* +* @param v +* Input value. +* +* @return +* Nearest power of two above input value. +*/ +static inline unsigned int +log2above (unsigned int v) +{ +unsigned int l; +unsigned int r; + +for (l =0 , r =0 ; (v >>1 ); ++l, v >>=1 ) + r |= (v &1 ); +return l + r; +} +#endif /* MLX4_UTILS_H_ */
Signature · 1 line
1.8.3.1
PATCH v4 3/7 net/mlx4: restore Rx scatter support
In reply to Ophir MunkCalculate the number of scatters on the fly according to the maximum expected packet size.
--- drivers/net/mlx4/mlx4_rxq.c | 64 +++++++++++++++++++++++++++++++++++++------- drivers/net/mlx4/mlx4_rxtx.c | 11 +++++--- drivers/net/mlx4/mlx4_rxtx.h | 1 + 3 files changed, 62 insertions(+), 14 deletions(-)
drivers/net/mlx4/mlx4_rxq.c +54 -10
@@ -78,6 +78,7 @@ mlx4_rxq_alloc_elts(struct rxq *rxq, unsigned int elts_n) {unsigned int i; +const uint32_t sges_n =1 << rxq->sges_n;struct rte_mbuf *(*elts)[elts_n] =rte_calloc_socket ("RXQ" ,1 ,sizeof (*elts),0 , rxq->socket);
@@ -101,6 +102,9 @@/* Buffer is supposed to be empty. */ assert (rte_pktmbuf_data_len (buf) ==0 );assert (rte_pktmbuf_pkt_len (buf) ==0 ); +/* Only the first segment keeps headroom. */ +if (i % sges_n) + buf->data_off =0 ; buf->port = rxq->port_id; buf->data_len =rte_pktmbuf_tailroom (buf); buf->pkt_len =rte_pktmbuf_tailroom (buf);
@@ -113,8 +117,8 @@ }; (*elts)[i] = buf; } -DEBUG ("%p: allocated and configured %u single-segment WRs" , - (void *)rxq, elts_n); +DEBUG ("%p: allocated and configured %u segments (max %u packets)" , + (void *)rxq, elts_n, elts_n >> rxq->sges_n); rxq->elts_n =log2above (elts_n); rxq->elts = elts;return 0 ;
@@ -185,12 +189,15 @@* Completion queue to associate with QP. * @param desc * Number of descriptors in QP (hint only). +* @param sges_n +* Maximum number of segments per packet. * * @return * QP pointer or NULL in case of error and rte_errno is set. */ static struct ibv_qp * -mlx4_rxq_setup_qp (struct priv *priv,struct ibv_cq *cq,uint16_t desc) +mlx4_rxq_setup_qp (struct priv *priv,struct ibv_cq *cq,uint16_t desc, +uint32_t sges_n) {struct ibv_qp *qp;struct ibv_qp_init_attr attr = {
@@ -204,7 +211,7 @@ priv->device_attr.max_qp_wr : desc), /* Maximum number of segments per packet. */ - .max_recv_sge = 1, + .max_recv_sge = sges_n, }, .qp_type = IBV_QPT_RAW_PACKET, };
@@ -263,11 +270,31 @@assert (mb_len >=RTE_PKTMBUF_HEADROOM );if (dev->data->dev_conf.rxmode.max_rx_pkt_len <= (mb_len -RTE_PKTMBUF_HEADROOM )) { - ; + tmpl.sges_n =0 ; }else if (dev->data->dev_conf.rxmode.enable_scatter) { -WARN ("%p: scattered mode has been requested but is" -" not supported, this may lead to packet loss" , - (void *)dev); +uint32_t size = +RTE_PKTMBUF_HEADROOM + + dev->data->dev_conf.rxmode.max_rx_pkt_len; +uint32_t sges_n; + +/* +* Determine the number of SGEs needed for a full packet +* and round it to the next power of two. +*/ + sges_n =log2above ((size / mb_len) + !!(size % mb_len)); + tmpl.sges_n = sges_n; +/* Make sure sges_n did not overflow. */ + size = mb_len * (1 << tmpl.sges_n); + size -=RTE_PKTMBUF_HEADROOM ; +if (size < dev->data->dev_conf.rxmode.max_rx_pkt_len) { + rte_errno =EOVERFLOW ; +ERROR ("%p: too many SGEs (%u) needed to handle" +" requested maximum packet size %u" , + (void *)dev, +1 << sges_n, + dev->data->dev_conf.rxmode.max_rx_pkt_len); + goto error; + } }else {WARN ("%p: the requested maximum Rx packet size (%u) is" " larger than a single mbuf (%u) and scattered"
@@ -276,6 +303,17 @@ dev->data->dev_conf.rxmode.max_rx_pkt_len, mb_len - RTE_PKTMBUF_HEADROOM); } +DEBUG ("%p: maximum number of segments per packet: %u" , + (void *)dev,1 << tmpl.sges_n); +if (desc % (1 << tmpl.sges_n)) { + rte_errno =EINVAL ; +ERROR ("%p: number of RX queue descriptors (%u) is not a" +" multiple of maximum segments per packet (%u)" , + (void *)dev, + desc, +1 << tmpl.sges_n); + goto error; + }/* Use the entire Rx mempool as the memory region. */ tmpl.mr =mlx4_mp2mr (priv->pd, mp);if (tmpl.mr ==NULL ) {
@@ -300,7 +338,8 @@ goto error; } } - tmpl.cq =ibv_create_cq (priv->ctx, desc,NULL , tmpl.channel,0 ); + tmpl.cq =ibv_create_cq (priv->ctx, desc >> tmpl.sges_n,NULL , + tmpl.channel,0 );if (tmpl.cq ==NULL ) { rte_errno =ENOMEM ; ERROR("%p: CQ creation failure: %s",
@@ -311,7 +350,8 @@ priv->device_attr.max_qp_wr);DEBUG ("priv->device_attr.max_sge is %d" , priv->device_attr.max_sge); - tmpl.qp =mlx4_rxq_setup_qp (priv, tmpl.cq, desc); + tmpl.qp =mlx4_rxq_setup_qp (priv, tmpl.cq, desc >> tmpl.sges_n, +1 << tmpl.sges_n);if (tmpl.qp ==NULL ) {ERROR ("%p: QP creation failure: %s" , (void *)dev,strerror (rte_errno));
@@ -373,6 +413,10 @@mlx4_rxq_cleanup (rxq); *rxq = tmpl;DEBUG ("%p: rxq updated with %p" , (void *)rxq, (void *)&tmpl); +/* Update doorbell counter. */ + rxq->rq_ci = desc >> rxq->sges_n; +rte_wmb (); + *rxq->rq_db =rte_cpu_to_be_32 (rxq->rq_ci);return 0 ; error: ret = rte_errno;
drivers/net/mlx4/mlx4_rxtx.c +7 -4
@@ -563,10 +563,11 @@ {struct rxq *rxq = dpdk_rxq;const uint32_t wr_cnt = (1 << rxq->elts_n) -1 ; +const uint16_t sges_n = rxq->sges_n;struct rte_mbuf *pkt =NULL ;struct rte_mbuf *seg =NULL ;unsigned int i =0 ; -uint32_t rq_ci = rxq->rq_ci; +uint32_t rq_ci = rxq->rq_ci << sges_n;int len =0 ;while (pkts_n) {
@@ -646,13 +647,15 @@ --pkts_n; ++i; skip: -/* Update consumer index */ +/* Align consumer index to the next stride. */ + rq_ci >>= sges_n; ++rq_ci; + rq_ci <<= sges_n; } -if (unlikely (i ==0 && rq_ci == rxq->rq_ci)) +if (unlikely (i ==0 && (rq_ci >> sges_n) == rxq->rq_ci))return 0 ;/* Update the consumer index. */ - rxq->rq_ci = rq_ci; + rxq->rq_ci = rq_ci >> sges_n;rte_wmb (); *rxq->rq_db =rte_cpu_to_be_32 (rxq->rq_ci); *rxq->mcq.set_ci_db =rte_cpu_to_be_32 (rxq->mcq.cons_index &0xffffff );
drivers/net/mlx4/mlx4_rxtx.h +1 -0
@@ -72,6 +72,7 @@ struct rxq {struct ibv_comp_channel *channel;/**< Rx completion channel. */ uint16_t rq_ci;/**< Saved RQ consumer index. */ uint16_t port_id;/**< Port ID for incoming packets. */ +uint16_t sges_n;/**< Number of segments per packet (log2 value). */ uint16_t elts_n;/**< Mbuf queue size (log2 value). */ struct rte_mbuf *(*elts)[];/**< Rx elements. */ volatile struct mlx4_wqe_data_seg (*wqes)[];/**< HW queue entries. */
Signature · 1 line
1.8.3.1
PATCH v4 4/7 net/mlx4: restore Tx gather support
In reply to Ophir MunkFrom: Moti Haimovsky <[email protected]>
This patch adds support for transmitting packets spanning over multiple buffers.
In this patch we also take into consideration the amount of entries a packet occupies in the TxQ when setting the report-completion flag of the chip.
--- drivers/net/mlx4/mlx4_rxtx.c | 197 +++++++++++++++++++++++++------------------ drivers/net/mlx4/mlx4_rxtx.h | 6 +- drivers/net/mlx4/mlx4_txq.c | 12 ++- 3 files changed, 127 insertions(+), 88 deletions(-)
drivers/net/mlx4/mlx4_rxtx.c +113 -84
@@ -63,6 +63,15 @@#include "mlx4_utils.h" /** +* Pointer-value pair structure used in tx_post_send for saving the first +* DWORD (32 byte) of a TXBB. +*/ +struct pv { +struct mlx4_wqe_data_seg *dseg; +uint32_t val; +}; + +/** * Stamp a WQE so it won't be reused by the HW. * * Routine is used when freeing WQE used by the chip or when failing
@@ -291,24 +300,28 @@* Target Tx queue. * @param pkt * Packet to transmit. -* @param send_flags -* @p MLX4_WQE_CTRL_CQ_UPDATE to request completion on this packet. * * @return * 0 on success, negative errno value otherwise and rte_errno is set. */ static inline int -mlx4_post_send (struct txq *txq,struct rte_mbuf *pkt,uint32_t send_flags) +mlx4_post_send (struct txq *txq,struct rte_mbuf *pkt) {struct mlx4_wqe_ctrl_seg *ctrl;struct mlx4_wqe_data_seg *dseg;struct mlx4_sq *sq = &txq->msq; +struct rte_mbuf *buf;uint32_t head_idx = sq->head & sq->txbb_cnt_mask;uint32_t lkey;uintptr_t addr; +uint32_t srcrb_flags; +uint32_t owner_opcode =MLX4_OPCODE_SEND ; +uint32_t byte_count;int wqe_real_size;int nr_txbbs;int rc; +struct pv *pv = (struct pv *)txq->bounce_buf; +int pv_counter =0 ;/* Calculate the needed work queue entry size for this packet. */ wqe_real_size = sizeof(struct mlx4_wqe_ctrl_seg) +
@@ -324,56 +337,81 @@ rc =ENOSPC ; goto err; } -/* Get the control and single-data entries of the WQE. */ +/* Get the control and data entries of the WQE. */ ctrl = (struct mlx4_wqe_ctrl_seg *)mlx4_get_send_wqe (sq, head_idx); dseg = (struct mlx4_wqe_data_seg *)((uintptr_t )ctrl +sizeof (struct mlx4_wqe_ctrl_seg )); -/* Fill the data segment with buffer information. */ - addr =rte_pktmbuf_mtod (pkt, uintptr_t); -rte_prefetch0 ((volatile void *)addr); - dseg->addr =rte_cpu_to_be_64 (addr); -/* Memory region key for this memory pool. */ - lkey =mlx4_txq_mp2mr (txq,mlx4_txq_mb2mp (pkt)); -if (unlikely (lkey == (uint32_t )-1 )) { -/* MR does not exist. */ -DEBUG ("%p: unable to get MP <-> MR association" , (void *)txq); +/* Fill the data segments with buffer information. */ +for (buf = pkt; buf !=NULL ; buf = buf->next, dseg++) { + addr =rte_pktmbuf_mtod (buf, uintptr_t); +rte_prefetch0 ((volatile void *)addr); +/* Handle WQE wraparound. */ +if (unlikely (dseg >= (struct mlx4_wqe_data_seg *)sq->eob)) + dseg = (struct mlx4_wqe_data_seg *)sq->buf; + dseg->addr =rte_cpu_to_be_64 (addr); +/* Memory region key for this memory pool. */ + lkey =mlx4_txq_mp2mr (txq,mlx4_txq_mb2mp (buf)); +if (unlikely (lkey == (uint32_t )-1 )) { +/* MR does not exist. */ +DEBUG ("%p: unable to get MP <-> MR association" , + (void *)txq); +/* +* Restamp entry in case of failure. +* Make sure that size is written correctly +* Note that we give ownership to the SW, not the HW. +*/ + ctrl->fence_size = (wqe_real_size >>4 ) &0x3f ; +mlx4_txq_stamp_freed_wqe (sq, head_idx, + (sq->head & sq->txbb_cnt) ?0 :1 ); + rc =EFAULT ; + goto err; + } + dseg->lkey =rte_cpu_to_be_32 (lkey); +if (likely (buf->data_len)) { + byte_count =rte_cpu_to_be_32 (buf->data_len); + }else { +/* +* Zero length segment is treated as inline segment +* with zero data. +*/ + byte_count =RTE_BE32 (0x80000000 ); + }/* -* Restamp entry in case of failure, make sure that size is -* written correctly. -* Note that we give ownership to the SW, not the HW. +* If the data segment is not at the beginning of a +* Tx basic block (TXBB) then write the byte count, +* else postpone the writing to just before updating the +* control segment. */ - ctrl->fence_size = (wqe_real_size >>4 ) &0x3f ; -mlx4_txq_stamp_freed_wqe (sq, head_idx, - (sq->head & sq->txbb_cnt) ?0 :1 ); - rc =EFAULT ; - goto err; +if ((uintptr_t )dseg & (uintptr_t )(MLX4_TXBB_SIZE -1 )) { +/* +* Need a barrier here before writing the byte_count +* fields to make sure that all the data is visible +* before the byte_count field is set. +* Otherwise, if the segment begins a new cacheline, +* the HCA prefetcher could grab the 64-byte chunk and +* get a valid (!= 0xffffffff) byte count but stale +* data, and end up sending the wrong data. +*/ +rte_io_wmb (); + dseg->byte_count = byte_count; + }else { +/* +* This data segment starts at the beginning of a new +* TXBB, so we need to postpone its byte_count writing +* for later. +*/ + pv[pv_counter].dseg = dseg; + pv[pv_counter++].val = byte_count; + } } - dseg->lkey =rte_cpu_to_be_32 (lkey); -/* -* Need a barrier here before writing the byte_count field to -* make sure that all the data is visible before the -* byte_count field is set. Otherwise, if the segment begins -* a new cache line, the HCA prefetcher could grab the 64-byte -* chunk and get a valid (!= 0xffffffff) byte count but -* stale data, and end up sending the wrong data. -*/ -rte_io_wmb (); -if (likely (pkt->data_len)) - dseg->byte_count =rte_cpu_to_be_32 (pkt->data_len); -else -/* -* Zero length segment is treated as inline segment -* with zero data. -*/ - dseg->byte_count =RTE_BE32 (0x80000000 ); -/* -* Fill the control parameters for this packet. -* For raw Ethernet, the SOLICIT flag is used to indicate that no ICRC -* should be calculated. -*/ - ctrl->srcrb_flags = -rte_cpu_to_be_32 (MLX4_WQE_CTRL_SOLICIT | - (send_flags &MLX4_WQE_CTRL_CQ_UPDATE )); +/* Write the first DWORD of each TXBB save earlier. */ +if (pv_counter) { +/* Need a barrier here before writing the byte_count. */ +rte_io_wmb (); +for (--pv_counter; pv_counter >=0 ; pv_counter--) + pv[pv_counter].dseg->byte_count = pv[pv_counter].val; + } +/* Fill the control parameters for this packet. */ ctrl->fence_size = (wqe_real_size >>4 ) &0x3f ;/* * The caller should prepare "imm" in advance in order to support
@@ -382,14 +420,27 @@*/ ctrl->imm =0 ;/* -* Make sure descriptor is fully written before setting ownership -* bit (because HW can start executing as soon as we do). +* For raw Ethernet, the SOLICIT flag is used to indicate that no ICRC +* should be calculated. +*/ + txq->elts_comp_cd -= nr_txbbs; +if (unlikely (txq->elts_comp_cd <=0 )) { + txq->elts_comp_cd = txq->elts_comp_cd_init; + srcrb_flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT | +MLX4_WQE_CTRL_CQ_UPDATE ); + }else { + srcrb_flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT ); + } + ctrl->srcrb_flags = srcrb_flags; +/* +* Make sure descriptor is fully written before +* setting ownership bit (because HW can start +* executing as soon as we do). */ rte_wmb (); - ctrl->owner_opcode = -rte_cpu_to_be_32 (MLX4_OPCODE_SEND | - ((sq->head & sq->txbb_cnt) ? -MLX4_BIT_WQE_OWN :0 )); + ctrl->owner_opcode =rte_cpu_to_be_32 (owner_opcode | + ((sq->head & sq->txbb_cnt) ? +MLX4_BIT_WQE_OWN :0 )); sq->head += nr_txbbs;return 0 ; err:
@@ -416,14 +467,13 @@struct txq *txq = (struct txq *)dpdk_txq;unsigned int elts_head = txq->elts_head;const unsigned int elts_n = txq->elts_n; -unsigned int elts_comp_cd = txq->elts_comp_cd;unsigned int elts_comp =0 ;unsigned int bytes_sent =0 ;unsigned int i;unsigned int max;int err; -assert (elts_comp_cd !=0 ); +assert (txq->elts_comp_cd !=0 );mlx4_txq_complete (txq); max = (elts_n - (elts_head - txq->elts_tail));if (max > elts_n)
@@ -442,8 +492,6 @@ (((elts_head +1 ) == elts_n) ?0 : elts_head +1 );struct txq_elt *elt_next = &(*txq->elts)[elts_head_next];struct txq_elt *elt = &(*txq->elts)[elts_head]; -unsigned int segs = buf->nb_segs; -uint32_t send_flags =0 ;/* Clean up old buffer. */ if (likely (elt->buf !=NULL )) {
@@ -461,34 +509,16 @@ tmp = next; }while (tmp !=NULL ); } -/* Request Tx completion. */ -if (unlikely (--elts_comp_cd ==0 )) { - elts_comp_cd = txq->elts_comp_cd_init; - ++elts_comp; - send_flags |=MLX4_WQE_CTRL_CQ_UPDATE ; - } -if (likely (segs ==1 )) { -/* Update element. */ - elt->buf = buf; -RTE_MBUF_PREFETCH_TO_FREE (elt_next->buf); -/* Post the packet for sending. */ - err =mlx4_post_send (txq, buf, send_flags); -if (unlikely (err)) { -if (unlikely (send_flags & -MLX4_WQE_CTRL_CQ_UPDATE )) { - elts_comp_cd =1 ; - --elts_comp; - } - elt->buf =NULL ; - goto stop; - } - elt->buf = buf; - bytes_sent += buf->pkt_len; - }else { - err = -EINVAL ; - rte_errno = -err; +RTE_MBUF_PREFETCH_TO_FREE (elt_next->buf); +/* Post the packet for sending. */ + err =mlx4_post_send (txq, buf); +if (unlikely (err)) { + elt->buf =NULL ; goto stop; } + elt->buf = buf; + bytes_sent += buf->pkt_len; + ++elts_comp; elts_head = elts_head_next; } stop:
@@ -504,7 +534,6 @@rte_write32 (txq->msq.doorbell_qpn, txq->msq.db); txq->elts_head = elts_head; txq->elts_comp += elts_comp; - txq->elts_comp_cd = elts_comp_cd;return i; }
drivers/net/mlx4/mlx4_rxtx.h +4 -2
@@ -101,13 +101,15 @@ struct txq {struct mlx4_cq mcq;/**< Info for directly manipulating the CQ. */ unsigned int elts_head;/**< Current index in (*elts)[]. */ unsigned int elts_tail;/**< First element awaiting completion. */ -unsigned int elts_comp;/**< Number of completion requests. */ -unsigned int elts_comp_cd;/**< Countdown for next completion. */ +unsigned int elts_comp;/**< Number of packets awaiting completion. */ +int elts_comp_cd;/**< Countdown for next completion. */ unsigned int elts_comp_cd_init;/**< Initial value for countdown. */ unsigned int elts_n;/**< (*elts)[] length. */ struct txq_elt (*elts)[];/**< Tx elements. */ struct mlx4_txq_stats stats;/**< Tx queue counters. */ uint32_t max_inline;/**< Max inline send size. */ +uint8_t *bounce_buf; +/**< Memory used for storing the first DWORD of data TXBBs. */ struct {const struct rte_mempool *mp;/**< Cached memory pool. */ struct ibv_mr *mr;/**< Memory region (for mp). */
drivers/net/mlx4/mlx4_txq.c +10 -2
@@ -83,8 +83,13 @@rte_calloc_socket ("TXQ" ,1 ,sizeof (*elts),0 , txq->socket);int ret =0 ; -if (elts ==NULL ) { -ERROR ("%p: can't allocate packets array" , (void *)txq); +/* Allocate bounce buffer. */ + txq->bounce_buf =rte_zmalloc_socket ("TXQ" , +MLX4_MAX_WQE_SIZE , +RTE_CACHE_LINE_MIN_SIZE , + txq->socket); +if (!elts || !txq->bounce_buf) { +ERROR ("%p: can't allocate TXQ memory" , (void *)txq); ret =ENOMEM ; goto error; }
@@ -110,6 +115,8 @@assert (ret ==0 );return 0 ; error: +rte_free (txq->bounce_buf); + txq->bounce_buf =NULL ;rte_free (elts);DEBUG ("%p: failed, freed everything" , (void *)txq);assert (ret >0 );
@@ -175,6 +182,7 @@claim_zero (ibv_destroy_qp (txq->qp));if (txq->cq !=NULL )claim_zero (ibv_destroy_cq (txq->cq)); +rte_free (txq->bounce_buf);for (i =0 ; (i !=RTE_DIM (txq->mp2mr)); ++i) {if (txq->mp2mr[i].mp ==NULL )break ;
Signature · 1 line
1.8.3.1
PATCH v4 5/7 net/mlx4: restore Tx checksum offloads
In reply to Ophir MunkFrom: Moti Haimovsky <[email protected]>
This patch adds hardware offloading support for IPv4, UDP and TCP checksum calculation, including inner/outer checksums on supported tunnel types.
--- drivers/net/mlx4/mlx4.c | 11 +++++++++++ drivers/net/mlx4/mlx4.h | 2 ++ drivers/net/mlx4/mlx4_ethdev.c | 6 ++++++ drivers/net/mlx4/mlx4_prm.h | 2 ++ drivers/net/mlx4/mlx4_rxtx.c | 19 +++++++++++++++++++ drivers/net/mlx4/mlx4_rxtx.h | 2 ++ drivers/net/mlx4/mlx4_txq.c | 2 ++ 7 files changed, 44 insertions(+)
drivers/net/mlx4/mlx4.c +11 -0
@@ -529,6 +529,17 @@ struct mlx4_conf { priv->pd = pd; priv->mtu =ETHER_MTU ; priv->vf = vf; + priv->hw_csum = !!(device_attr.device_cap_flags & +IBV_DEVICE_RAW_IP_CSUM ); +DEBUG ("checksum offloading is %ssupported" , + (priv->hw_csum ?"" :"not " )); +/* Only ConnectX-3 Pro supports tunneling. */ + priv->hw_csum_l2tun = + priv->hw_csum && + (device_attr.vendor_part_id == +PCI_DEVICE_ID_MELLANOX_CONNECTX3PRO ); +DEBUG ("L2 tunnel checksum offloads are %ssupported" , + (priv->hw_csum_l2tun ?"" :"not " ));/* Configure the first MAC address by default. */ if (mlx4_get_mac (priv, &mac.addr_bytes)) { ERROR("cannot get MAC address, is mlx4_en loaded?"
drivers/net/mlx4/mlx4.h +2 -0
@@ -104,6 +104,8 @@ struct priv { unsigned int vf:1; /* This is a VF device. */ unsigned int intr_alarm:1; /* An interrupt alarm is scheduled. */ unsigned int isolated:1; /* Toggle isolated mode. */ + unsigned int hw_csum:1; /* Checksum offload is supported. */ + unsigned int hw_csum_l2tun:1; /* Checksum support for L2 tunnels. */struct rte_intr_handle intr_handle;/* Port interrupt handle. */ struct rte_flow_drop *flow_drop_queue;/* Flow drop queue. */ LIST_HEAD(mlx4_flows, rte_flow) flows;
drivers/net/mlx4/mlx4_ethdev.c +6 -0
@@ -553,6 +553,12 @@ info->max_mac_addrs =1 ; info->rx_offload_capa =0 ; info->tx_offload_capa =0 ; +if (priv->hw_csum) + info->tx_offload_capa |= (DEV_TX_OFFLOAD_IPV4_CKSUM | +DEV_TX_OFFLOAD_UDP_CKSUM | +DEV_TX_OFFLOAD_TCP_CKSUM ); +if (priv->hw_csum_l2tun) + info->tx_offload_capa |=DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM ;if (mlx4_get_ifname (priv, &ifname) ==0 ) info->if_index =if_nametoindex (ifname); info->speed_capa =
drivers/net/mlx4/mlx4_prm.h +2 -0
@@ -64,6 +64,8 @@/* Work queue element (WQE) flags. */ #define MLX4_BIT_WQE_OWN 0x80000000 +#define MLX4_WQE_CTRL_IIP_HDR_CSUM (1 << 28) +#define MLX4_WQE_CTRL_IL4_HDR_CSUM (1 << 27)#define MLX4_SIZE_TO_TXBBS (size) \ (RTE_ALIGN((size), (MLX4_TXBB_SIZE)) >> (MLX4_TXBB_SHIFT))
drivers/net/mlx4/mlx4_rxtx.c +19 -0
@@ -431,6 +431,25 @@ struct pv { }else { srcrb_flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT ); } +/* Enable HW checksum offload if requested */ +if (txq->csum && + (pkt->ol_flags & + (PKT_TX_IP_CKSUM |PKT_TX_TCP_CKSUM |PKT_TX_UDP_CKSUM ))) { +const uint64_t is_tunneled = (pkt->ol_flags & + (PKT_TX_TUNNEL_GRE | +PKT_TX_TUNNEL_VXLAN )); + +if (is_tunneled && txq->csum_l2tun) { + owner_opcode |=MLX4_WQE_CTRL_IIP_HDR_CSUM | +MLX4_WQE_CTRL_IL4_HDR_CSUM ; +if (pkt->ol_flags &PKT_TX_OUTER_IP_CKSUM ) + srcrb_flags |= +RTE_BE32 (MLX4_WQE_CTRL_IP_HDR_CSUM ); + }else { + srcrb_flags |=RTE_BE32 (MLX4_WQE_CTRL_IP_HDR_CSUM | +MLX4_WQE_CTRL_TCP_UDP_CSUM ); + } + } ctrl->srcrb_flags = srcrb_flags;/* * Make sure descriptor is fully written before
drivers/net/mlx4/mlx4_rxtx.h +2 -0
@@ -108,6 +108,8 @@ struct txq {struct txq_elt (*elts)[];/**< Tx elements. */ struct mlx4_txq_stats stats;/**< Tx queue counters. */ uint32_t max_inline;/**< Max inline send size. */ + uint32_t csum:1; /**< Enable checksum offloading. */ + uint32_t csum_l2tun:1; /**< Same for L2 tunnels. */uint8_t *bounce_buf;/**< Memory used for storing the first DWORD of data TXBBs. */ struct {
drivers/net/mlx4/mlx4_txq.c +2 -0
@@ -338,6 +338,8 @@ struct txq_mp2mr_mbuf_check_data { (void *)dev, strerror(rte_errno)); goto error; } + tmpl.csum = priv->hw_csum; + tmpl.csum_l2tun = priv->hw_csum_l2tun;DEBUG ("priv->device_attr.max_qp_wr is %d" , priv->device_attr.max_qp_wr); DEBUG("priv->device_attr.max_sge is %d",
Signature · 1 line
1.8.3.1
PATCH v4 6/7 net/mlx4: restore Rx offloads
In reply to Ophir MunkFrom: Moti Haimovsky <[email protected]>
This patch adds hardware offloading support for IPV4, UDP and TCP checksum verification, including inner/outer checksums on supported tunnel types.
It also restores packet type recognition support.
--- drivers/net/mlx4/mlx4_ethdev.c | 6 ++- drivers/net/mlx4/mlx4_prm.h | 30 +++++++++++ drivers/net/mlx4/mlx4_rxq.c | 5 ++ drivers/net/mlx4/mlx4_rxtx.c | 118 ++++++++++++++++++++++++++++++++++++++++- drivers/net/mlx4/mlx4_rxtx.h | 2 + 5 files changed, 158 insertions(+), 3 deletions(-)
drivers/net/mlx4/mlx4_ethdev.c +5 -1
@@ -553,10 +553,14 @@ info->max_mac_addrs =1 ; info->rx_offload_capa =0 ; info->tx_offload_capa =0 ; -if (priv->hw_csum) +if (priv->hw_csum) { info->tx_offload_capa |= (DEV_TX_OFFLOAD_IPV4_CKSUM |DEV_TX_OFFLOAD_UDP_CKSUM |DEV_TX_OFFLOAD_TCP_CKSUM ); + info->rx_offload_capa |= (DEV_RX_OFFLOAD_IPV4_CKSUM | +DEV_RX_OFFLOAD_UDP_CKSUM | +DEV_RX_OFFLOAD_TCP_CKSUM ); + }if (priv->hw_csum_l2tun) info->tx_offload_capa |=DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM ;if (mlx4_get_ifname (priv, &ifname) ==0 )
drivers/net/mlx4/mlx4_prm.h +30 -0
@@ -70,6 +70,14 @@#define MLX4_SIZE_TO_TXBBS (size) \ (RTE_ALIGN((size), (MLX4_TXBB_SIZE)) >> (MLX4_TXBB_SHIFT)) +/* CQE checksum flags. */ +enum { +MLX4_CQE_L2_TUNNEL_IPV4 = (int )(1u <<25 ), +MLX4_CQE_L2_TUNNEL_L4_CSUM = (int )(1u <<26 ), +MLX4_CQE_L2_TUNNEL = (int )(1u <<27 ), +MLX4_CQE_L2_TUNNEL_IPOK = (int )(1u <<31 ), +}; +/* Send queue information. */ struct mlx4_sq {uint8_t *buf;/**< SQ buffer. */
@@ -119,4 +127,26 @@ struct mlx4_cq { (cq->cqe_64 << 5)); } +/** +* Transpose a flag in a value. +* +* @param val +* Input value. +* @param from +* Flag to retrieve from input value. +* @param to +* Flag to set in output value. +* +* @return +* Output value with transposed flag enabled if present on input. +*/ +static inline uint64_t +mlx4_transpose (uint64_t val,uint64_t from,uint64_t to) +{ +return (from >= to ? + (val & from) / (from / to) : + (val & from) * (to / from)); +} + +#endif /* MLX4_PRM_H_ */
drivers/net/mlx4/mlx4_rxq.c +5 -0
@@ -260,6 +260,11 @@int ret; (void )conf;/* Thresholds configuration (ignored). */ +/* Toggle Rx checksum offload if hardware supports it. */ +if (priv->hw_csum) + tmpl.csum = !!dev->data->dev_conf.rxmode.hw_ip_checksum; +if (priv->hw_csum_l2tun) + tmpl.csum_l2tun = !!dev->data->dev_conf.rxmode.hw_ip_checksum; mb_len =rte_pktmbuf_data_room_size (mp);if (desc ==0 ) { rte_errno =EINVAL ;
drivers/net/mlx4/mlx4_rxtx.c +116 -2
130 lines not on this page · raw message
drivers/net/mlx4/mlx4_rxtx.h +2 -0
@@ -77,6 +77,8 @@ struct rxq {struct rte_mbuf *(*elts)[];/**< Rx elements. */ volatile struct mlx4_wqe_data_seg (*wqes)[];/**< HW queue entries. */ volatile uint32_t *rq_db;/**< RQ doorbell record. */ + uint32_t csum:1; /**< Enable checksum offloading. */ + uint32_t csum_l2tun:1; /**< Same for L2 tunnels. */struct mlx4_cq mcq;/**< Info for directly manipulating the CQ. */ struct mlx4_rxq_stats stats;/**< Rx queue counters. */ unsigned int socket;/**< CPU socket ID for allocations. */
Signature · 1 line
1.8.3.1
PATCH v4 7/7 net/mlx4: add loopback Tx from VF
In reply to Ophir MunkFrom: Moti Haimovsky <[email protected]>
This patch adds loopback functionality used when the chip is a VF in order to enable packet transmission between VFs and PF.
--- drivers/net/mlx4/mlx4_rxtx.c | 33 +++++++++++++++++++++------------ drivers/net/mlx4/mlx4_rxtx.h | 1 + drivers/net/mlx4/mlx4_txq.c | 2 ++ 3 files changed, 24 insertions(+), 12 deletions(-)
drivers/net/mlx4/mlx4_rxtx.c +21 -12
@@ -311,10 +311,13 @@ struct pv {struct mlx4_wqe_data_seg *dseg;struct mlx4_sq *sq = &txq->msq;struct rte_mbuf *buf; +union { +uint32_t flags; +uint16_t flags16[2 ]; + } srcrb;uint32_t head_idx = sq->head & sq->txbb_cnt_mask;uint32_t lkey;uintptr_t addr; -uint32_t srcrb_flags;uint32_t owner_opcode =MLX4_OPCODE_SEND ;uint32_t byte_count;int wqe_real_size;
@@ -414,22 +417,16 @@ struct pv {/* Fill the control parameters for this packet. */ ctrl->fence_size = (wqe_real_size >>4 ) &0x3f ;/* -* The caller should prepare "imm" in advance in order to support -* VF to VF communication (when the device is a virtual-function -* device (VF)). -*/ - ctrl->imm =0 ; -/* * For raw Ethernet, the SOLICIT flag is used to indicate that no ICRC * should be calculated. */ txq->elts_comp_cd -= nr_txbbs;if (unlikely (txq->elts_comp_cd <=0 )) { txq->elts_comp_cd = txq->elts_comp_cd_init; - srcrb_flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT | + srcrb.flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT |MLX4_WQE_CTRL_CQ_UPDATE ); }else { - srcrb_flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT ); + srcrb.flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT ); }/* Enable HW checksum offload if requested */ if (txq->csum &&
@@ -443,14 +440,26 @@ struct pv { owner_opcode |=MLX4_WQE_CTRL_IIP_HDR_CSUM |MLX4_WQE_CTRL_IL4_HDR_CSUM ;if (pkt->ol_flags &PKT_TX_OUTER_IP_CKSUM ) - srcrb_flags |= + srcrb.flags |=RTE_BE32 (MLX4_WQE_CTRL_IP_HDR_CSUM ); }else { - srcrb_flags |=RTE_BE32 (MLX4_WQE_CTRL_IP_HDR_CSUM | + srcrb.flags |=RTE_BE32 (MLX4_WQE_CTRL_IP_HDR_CSUM |MLX4_WQE_CTRL_TCP_UDP_CSUM ); } } - ctrl->srcrb_flags = srcrb_flags; +if (txq->lb) { +/* +* Copy destination MAC address to the WQE, this allows +* loopback in eSwitch, so that VFs and PF can communicate +* with each other. +*/ + srcrb.flags16[0] = *(rte_pktmbuf_mtod(pkt, uint16_t *)); + ctrl->imm = *(rte_pktmbuf_mtod_offset (pkt ,uint32_t *, + sizeof(uint16_t))); + }else { + ctrl->imm =0 ; + } + ctrl->srcrb_flags = srcrb.flags;/* * Make sure descriptor is fully written before * setting ownership bit (because HW can start
drivers/net/mlx4/mlx4_rxtx.h +1 -0
@@ -112,6 +112,7 @@ struct txq {uint32_t max_inline;/**< Max inline send size. */ uint32_t csum:1; /**< Enable checksum offloading. */ uint32_t csum_l2tun:1; /**< Same for L2 tunnels. */ + uint32_t lb:1; /**< Whether packets should be looped back by eSwitch. */uint8_t *bounce_buf;/**< Memory used for storing the first DWORD of data TXBBs. */ struct {
drivers/net/mlx4/mlx4_txq.c +2 -0
@@ -412,6 +412,8 @@ struct txq_mp2mr_mbuf_check_data { (void *)dev, strerror(rte_errno)); goto error; } +/* Enable Tx loopback for VF devices. */ + tmpl.lb = !!(priv->vf);/* Clean up txq in case we're reinitializing it. */ DEBUG ("%p: cleaning-up old txq just in case" , (void *)txq);mlx4_txq_cleanup (txq);
Signature · 1 line
1.8.3.1
Re: [PATCH v4 0/7] new mlx4 datapath bypassing ibverbs
In reply to Ophir MunkQuoted 40 lines · Ophir Munk
v4 (Ophir):
- Split "net/mlx4: restore Rx scatter support" commit from "net/mlx4:
restore full Rx support bypassing Verbs" commitv3 (Adrien):
- Drop a few unrelated or unnecessary changes such as the removal ofMLX4_PMD_TX_MP_CACHE.
- Move device checksum support detection code to its previous location.
- Fix include guard inmlx4_prm.h.
- Reorder #includes alphabetically.
- ReplaceMLX4_TRANSPOSE()macro with documented inline function.
- Remove extra spaces and blank lines.
- Useuint8_t* instead of char * for buffers.
- Replacemlx4_get_cqe()macro with a documented inline function.
- Replace several unsigned int withuint32_t.
- Add consistency to field names (sge_n=>sges_n).
- Make mbuf size checks in RX queue setup function similar to mlx5.
- Update various comments.
- Fix indentation.
- Replace run-time endian conversion with static ones where possible.
- Reorder fields in struct rxq and struct txq for consistency, remove one level of unnecessary inner structures.
- Fix memory leak on Tx bounce buffer.
- Update commit logs.
- Fix remaining checkpatch warnings.v2 (Matan):
Rearange patches.
Semantics.
Enhancements.
Fix compilation issues.Moti Haimovsky (6):
net/mlx4: add simple Tx bypassing Verbs net/mlx4: restore full Rx support bypassing Verbs net/mlx4: restore Tx gather support net/mlx4: restore Tx checksum offloads net/mlx4: restore Rx offloads
net/mlx4: add loopback Tx from VF
Quoted 2 lines
Ophir Munk (1):
net/mlx4: restore Rx scatter support
Thanks Ophir for merging both v3's.
Ferruh, v4 supersedes all prior revisions (Moti's v1, Matan's v2, my own v3 and Ophir's v3-bis, I can't update patchwork for all of them).
For the entire series:
Signature · 2 lines
Adrien Mazarguil 6WIND
Re: [PATCH v4 0/7] new mlx4 datapath bypassing ibverbs
In reply to Ophir MunkQuoted 40 lines · Ophir Munk
v4 (Ophir):
- Split "net/mlx4: restore Rx scatter support" commit from "net/mlx4:
restore full Rx support bypassing Verbs" commitv3 (Adrien):
- Drop a few unrelated or unnecessary changes such as the removal ofMLX4_PMD_TX_MP_CACHE.
- Move device checksum support detection code to its previous location.
- Fix include guard inmlx4_prm.h.
- Reorder #includes alphabetically.
- ReplaceMLX4_TRANSPOSE()macro with documented inline function.
- Remove extra spaces and blank lines.
- Useuint8_t* instead of char * for buffers.
- Replacemlx4_get_cqe()macro with a documented inline function.
- Replace several unsigned int withuint32_t.
- Add consistency to field names (sge_n=>sges_n).
- Make mbuf size checks in RX queue setup function similar to mlx5.
- Update various comments.
- Fix indentation.
- Replace run-time endian conversion with static ones where possible.
- Reorder fields in struct rxq and struct txq for consistency, remove one level of unnecessary inner structures.
- Fix memory leak on Tx bounce buffer.
- Update commit logs.
- Fix remaining checkpatch warnings.v2 (Matan):
Rearange patches.
Semantics.
Enhancements.
Fix compilation issues.Moti Haimovsky (6):
net/mlx4: add simple Tx bypassing Verbs net/mlx4: restore full Rx support bypassing Verbs net/mlx4: restore Tx gather support net/mlx4: restore Tx checksum offloads net/mlx4: restore Rx offloads
net/mlx4: add loopback Tx from VF
Quoted 2 lines
Ophir Munk (1):
net/mlx4: restore Rx scatter support
Hi Ophir,
I am a little confused, can you please help me?
Currently both mlx4 and mlx5 should support both rdma-core and MLX-OFED, is this correct?
When I try to compile these patches with rdma-core, it is giving warning for shared library [1].
If I try to compile with mlx-ofed, getting missing header error [2].
What is the dependency for mlx4 driver now?
[1]
mlx4_rxq.o: In function `mlx4_rxq_setup':.../dpdk/drivers/net/mlx4/mlx4_rxq.c:393: undefined reference to `mlx4dv_init_obj'
mlx4_txq.o: In function `mlx4_txq_setup':.../dpdk/drivers/net/mlx4/mlx4_txq.c:429: undefined reference to `mlx4dv_init_obj'
[2]
In file included from .../drivers/net/mlx4/mlx4_flow.c:66:.../drivers/net/mlx4/mlx4_rxtx.h:43:10: fatal error:
'infiniband/mlx4dv.h' file not found
#include <infiniband/mlx4dv.h>
^~~~~~~~~~~~~~~~~~~~~Re: [PATCH v4 0/7] new mlx4 datapath bypassing ibverbs
Quoted 46 lines · Ferruh Yigit
Quoted 40 lines · Ophir Munk
v4 (Ophir):
- Split "net/mlx4: restore Rx scatter support" commit from "net/mlx4:
restore full Rx support bypassing Verbs" commitv3 (Adrien):
- Drop a few unrelated or unnecessary changes such as the removal ofMLX4_PMD_TX_MP_CACHE.
- Move device checksum support detection code to its previous location.
- Fix include guard inmlx4_prm.h.
- Reorder #includes alphabetically.
- ReplaceMLX4_TRANSPOSE()macro with documented inline function.
- Remove extra spaces and blank lines.
- Useuint8_t* instead of char * for buffers.
- Replacemlx4_get_cqe()macro with a documented inline function.
- Replace several unsigned int withuint32_t.
- Add consistency to field names (sge_n=>sges_n).
- Make mbuf size checks in RX queue setup function similar to mlx5.
- Update various comments.
- Fix indentation.
- Replace run-time endian conversion with static ones where possible.
- Reorder fields in struct rxq and struct txq for consistency, remove one level of unnecessary inner structures.
- Fix memory leak on Tx bounce buffer.
- Update commit logs.
- Fix remaining checkpatch warnings.v2 (Matan):
Rearange patches.
Semantics.
Enhancements.
Fix compilation issues.Moti Haimovsky (6):
net/mlx4: add simple Tx bypassing Verbs net/mlx4: restore full Rx support bypassing Verbs net/mlx4: restore Tx gather support net/mlx4: restore Tx checksum offloads net/mlx4: restore Rx offloads
net/mlx4: add loopback Tx from VFQuoted 2 lines
Ophir Munk (1):
net/mlx4: restore Rx scatter supportHi Ophir,
Quoted 7 lines
I am a little confused, can you please help me?
Currently both mlx4 and mlx5 should support both rdma-core and MLX-OFED, is this correct?
When I try to compile these patches with rdma-core, it is giving warning for shared library [1].
Ahh, this is because missing library in Makefile, can you please send a new version to fix this?
diff --git a/drivers/net/mlx4/Makefile b/drivers/net/mlx4/Makefile
index 0515cd7ef..3b3a02047 100644
--- a/drivers/net/mlx4/Makefile
+++ b/drivers/net/mlx4/Makefile
@@ -54,7 +54,7 @@ CFLAGS += -D_BSD_SOURCE
CFLAGS += -D_DEFAULT_SOURCE
CFLAGS += -D_XOPEN_SOURCE=600
CFLAGS += $(WERROR_FLAGS)
-LDLIBS += -libverbs
+LDLIBS += -libverbs -lmlx4# A few warnings cannot be avoided in external headers. CFLAGS += -Wno-error=cast-qual
Quoted 2 lines
If I try to compile with mlx-ofed, getting missing header error [2].
Can you please clarify this?
Quoted 20 lines
What is the dependency for mlx4 driver now?
[1]
mlx4_rxq.o: In function `mlx4_rxq_setup':.../dpdk/drivers/net/mlx4/mlx4_rxq.c:393: undefined reference to `mlx4dv_init_obj'
mlx4_txq.o: In function `mlx4_txq_setup':.../dpdk/drivers/net/mlx4/mlx4_txq.c:429: undefined reference to `mlx4dv_init_obj'[2]
In file included from.../drivers/net/mlx4/mlx4_flow.c:66:.../drivers/net/mlx4/mlx4_rxtx.h:43:10: fatal error:
'infiniband/mlx4dv.h' file not found#include <infiniband/mlx4dv.h> ^~~~~~~~~~~~~~~~~~~~~
v5 cover new mlx4 datapath bypassing ibverbs
In reply to Ophir MunkHopefully the last iteration for this series.
v5 (Ophir & Adrien):
- Merged Rx scatter/Tx gather code back into individual Rx/Tx commits for consistency due to a couple of issues with gather-less Tx.
- Rebased on top of the latest mlx4 control path changes (RSS support).
v4 (Ophir):
- Split "net/mlx4: restore Rx scatter support" commit from "net/mlx4:
restore full Rx support bypassing Verbs" commit
v3 (Adrien):
- Drop a few unrelated or unnecessary changes such as the removal of MLX4_PMD_TX_MP_CACHE.
- Move device checksum support detection code to its previous location.
- Fix include guard in mlx4_prm.h.
- Reorder #includes alphabetically.
- Replace MLX4_TRANSPOSE() macro with documented inline function.
- Remove extra spaces and blank lines.
- Use uint8_t * instead of char * for buffers.
- Replace mlx4_get_cqe() macro with a documented inline function.
- Replace several unsigned int with uint32_t.
- Add consistency to field names (sge_n => sges_n).
- Make mbuf size checks in RX queue setup function similar to mlx5.
- Update various comments.
- Fix indentation.
- Replace run-time endian conversion with static ones where possible.
- Reorder fields in struct rxq and struct txq for consistency, remove one level of unnecessary inner structures.
- Fix memory leak on Tx bounce buffer.
- Update commit logs.
- Fix remaining checkpatch warnings.
v2 (Matan):
Rearange patches.
Semantics.
Enhancements.
Fix compilation issues.
Moti Haimovsky (5):
net/mlx4: add Tx bypassing Verbs
net/mlx4: add Rx bypassing Verbs
net/mlx4: restore Tx checksum offloads
net/mlx4: restore Rx offloads
net/mlx4: add loopback Tx from VF
drivers/net/mlx4/mlx4.c | 11 + drivers/net/mlx4/mlx4.h | 2 + drivers/net/mlx4/mlx4_ethdev.c | 10 + drivers/net/mlx4/mlx4_prm.h | 151 +++++++ drivers/net/mlx4/mlx4_rxq.c | 156 +++++--- drivers/net/mlx4/mlx4_rxtx.c | 768 ++++++++++++++++++++++++++---------- drivers/net/mlx4/mlx4_rxtx.h | 54 +-- drivers/net/mlx4/mlx4_txq.c | 63 +++ 8 files changed, 942 insertions(+), 273 deletions(-) create mode 100644 drivers/net/mlx4/mlx4_prm.h
Signature · 1 line
2.1.4
PATCH v5 1/5 net/mlx4: add Tx bypassing Verbs
From: Moti Haimovsky <[email protected]>
Modify PMD to send single-buffer packets directly to the device bypassing the Verbs Tx post and poll routines.
Tx gather support: add support for transmitting packets spanning over multiple buffers.
Take into consideration the amount of entries a packet occupies in the TxQ when setting the report-completion flag of the chip.
--- drivers/net/mlx4/mlx4_prm.h | 120 ++++++++++++ drivers/net/mlx4/mlx4_rxtx.c | 398 ++++++++++++++++++++++++++++---------- drivers/net/mlx4/mlx4_rxtx.h | 30 +-- drivers/net/mlx4/mlx4_txq.c | 59 ++++++ 4 files changed, 490 insertions(+), 117 deletions(-)
drivers/net/mlx4/mlx4_prm.h new file +120 -0
@@ -0,0 +1,120 @@ +/*- +* BSD LICENSE +* +* Copyright 2017 6WIND S.A. +* Copyright 2017 Mellanox +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of 6WIND S.A. nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef MLX4_PRM_H_ +#define MLX4_PRM_H_ + +#include <rte_atomic.h> +#include <rte_branch_prediction.h> +#include <rte_byteorder.h> + +/* Verbs headers do not support -pedantic. */ +#ifdef PEDANTIC +#pragma GCC diagnostic ignored "-Wpedantic" +#endif +#include <infiniband/mlx4dv.h> +#include <infiniband/verbs.h> +#ifdef PEDANTIC +#pragma GCC diagnostic error "-Wpedantic" +#endif + +/* ConnectX-3 Tx queue basic block. */ +#define MLX4_TXBB_SHIFT 6 +#define MLX4_TXBB_SIZE (1 << MLX4_TXBB_SHIFT) + +/* Typical TSO descriptor with 16 gather entries is 352 bytes. */ +#define MLX4_MAX_WQE_SIZE 512 +#define MLX4_MAX_WQE_TXBBS (MLX4_MAX_WQE_SIZE / MLX4_TXBB_SIZE) + +/* Send queue stamping/invalidating information. */ +#define MLX4_SQ_STAMP_STRIDE 64 +#define MLX4_SQ_STAMP_DWORDS (MLX4_SQ_STAMP_STRIDE / 4) +#define MLX4_SQ_STAMP_SHIFT 31 +#define MLX4_SQ_STAMP_VAL 0x7fffffff + +/* Work queue element (WQE) flags. */ +#define MLX4_BIT_WQE_OWN 0x80000000 + +#define MLX4_SIZE_TO_TXBBS (size) \ + (RTE_ALIGN((size), (MLX4_TXBB_SIZE)) >> (MLX4_TXBB_SHIFT)) + +/* Send queue information. */ +struct mlx4_sq { +uint8_t *buf;/**< SQ buffer. */ +uint8_t *eob;/**< End of SQ buffer */ +uint32_t head;/**< SQ head counter in units of TXBBS. */ +uint32_t tail;/**< SQ tail counter in units of TXBBS. */ +uint32_t txbb_cnt;/**< Num of WQEBB in the Q (should be ^2). */ +uint32_t txbb_cnt_mask;/**< txbbs_cnt mask (txbb_cnt is ^2). */ +uint32_t headroom_txbbs;/**< Num of txbbs that should be kept free. */ +uint32_t *db;/**< Pointer to the doorbell. */ +uint32_t doorbell_qpn;/**< qp number to write to the doorbell. */ +}; + +#define mlx4_get_send_wqe (sq, n) ((sq)->buf + ((n) * (MLX4_TXBB_SIZE))) + +/* Completion queue information. */ +struct mlx4_cq { +uint8_t *buf;/**< Pointer to the completion queue buffer. */ +uint32_t cqe_cnt;/**< Number of entries in the queue. */ +uint32_t cqe_64:1 ;/**< CQ entry size is 64 bytes. */ +uint32_t cons_index;/**< Last queue entry that was handled. */ +uint32_t *set_ci_db;/**< Pointer to the completion queue doorbell. */ +}; + +/** +* Retrieve a CQE entry from a CQ. +* +* cqe = cq->buf + cons_index * cqe_size + cqe_offset +* +* Where cqe_size is 32 or 64 bytes and cqe_offset is 0 or 32 (depending on +* cqe_size). +* +* @param cq +* CQ to retrieve entry from. +* @param index +* Entry index. +* +* @return +* Pointer to CQE entry. +*/ +static inline struct mlx4_cqe * +mlx4_get_cqe (struct mlx4_cq *cq,uint32_t index) +{ +return (struct mlx4_cqe *)(cq->buf + + ((index & (cq->cqe_cnt -1 )) << + (5 + cq->cqe_64)) + + (cq->cqe_64 <<5 )); +} + +#endif /* MLX4_PRM_H_ */
drivers/net/mlx4/mlx4_rxtx.c +294 -104
469 lines not on this page · raw message
drivers/net/mlx4/mlx4_rxtx.h +17 -13
@@ -41,6 +41,7 @@#ifdef PEDANTIC #pragma GCC diagnostic ignored "-Wpedantic"#endif +#include <infiniband/mlx4dv.h> #include <infiniband/verbs.h> #ifdef PEDANTIC #pragma GCC diagnostic error "-Wpedantic"
@@ -51,6 +52,7 @@#include <rte_mempool.h> #include "mlx4.h" +#include "mlx4_prm.h" /** Rx queue counters. */ struct mlx4_rxq_stats {
@@ -101,8 +103,6 @@ struct mlx4_rss {/** Tx element. */ struct txq_elt { -struct ibv_send_wr wr;/**< Work request. */ -struct ibv_sge sge;/**< Scatter/gather element. */ struct rte_mbuf *buf;/**< Buffer. */ };
@@ -116,24 +116,28 @@ struct mlx4_txq_stats {/** Tx queue descriptor. */ struct txq { -struct priv *priv;/**< Back pointer to private data. */ +struct mlx4_sq msq;/**< Info for directly manipulating the SQ. */ +struct mlx4_cq mcq;/**< Info for directly manipulating the CQ. */ +unsigned int elts_head;/**< Current index in (*elts)[]. */ +unsigned int elts_tail;/**< First element awaiting completion. */ +unsigned int elts_comp;/**< Number of packets awaiting completion. */ +int elts_comp_cd;/**< Countdown for next completion. */ +unsigned int elts_comp_cd_init;/**< Initial value for countdown. */ +unsigned int elts_n;/**< (*elts)[] length. */ +struct txq_elt (*elts)[];/**< Tx elements. */ +struct mlx4_txq_stats stats;/**< Tx queue counters. */ +uint32_t max_inline;/**< Max inline send size. */ +uint8_t *bounce_buf; +/**< Memory used for storing the first DWORD of data TXBBs. */ struct {const struct rte_mempool *mp;/**< Cached memory pool. */ struct ibv_mr *mr;/**< Memory region (for mp). */ uint32_t lkey;/**< mr->lkey copy. */ } mp2mr[MLX4_PMD_TX_MP_CACHE ];/**< MP to MR translation table. */ +struct priv *priv;/**< Back pointer to private data. */ +unsigned int socket;/**< CPU socket ID for allocations. */ struct ibv_cq *cq;/**< Completion queue. */ struct ibv_qp *qp;/**< Queue pair. */ -uint32_t max_inline;/**< Max inline send size. */ -unsigned int elts_n;/**< (*elts)[] length. */ -struct txq_elt (*elts)[];/**< Tx elements. */ -unsigned int elts_head;/**< Current index in (*elts)[]. */ -unsigned int elts_tail;/**< First element awaiting completion. */ -unsigned int elts_comp;/**< Number of completion requests. */ -unsigned int elts_comp_cd;/**< Countdown for next completion. */ -unsigned int elts_comp_cd_init;/**< Initial value for countdown. */ -struct mlx4_txq_stats stats;/**< Tx queue counters. */ -unsigned int socket;/**< CPU socket ID for allocations. */ uint8_t data[];/**< Remaining queue resources. */ };
drivers/net/mlx4/mlx4_txq.c +59 -0
98 lines not on this page · raw message
Signature · 1 line
2.1.4
PATCH v5 2/5 net/mlx4: add Rx bypassing Verbs
In reply to Adrien MazarguilFrom: Moti Haimovsky <[email protected]>
This patch adds support for accessing the hardware directly when handling Rx packets eliminating the need to use Verbs in the Rx data path.
Rx scatter support: calculate the number of scatters on the fly according to the maximum expected packet size.
--- drivers/net/mlx4/mlx4_rxq.c | 151 +++++++++++++++++-------- drivers/net/mlx4/mlx4_rxtx.c | 226 +++++++++++++++++++++----------------- drivers/net/mlx4/mlx4_rxtx.h | 19 ++-- 3 files changed, 241 insertions(+), 155 deletions(-)
drivers/net/mlx4/mlx4_rxq.c +105 -46
@@ -51,6 +51,7 @@#pragma GCC diagnostic error "-Wpedantic"#endif +#include <rte_byteorder.h> #include <rte_common.h> #include <rte_errno.h> #include <rte_ethdev.h>
@@ -312,45 +313,46 @@ void mlx4_rss_detach(struct mlx4_rss *rss)static int mlx4_rxq_alloc_elts (struct rxq *rxq) { -struct rxq_elt (*elts)[rxq->elts_n] = rxq->elts; +const uint32_t elts_n =1 << rxq->elts_n; +const uint32_t sges_n =1 << rxq->sges_n; +struct rte_mbuf *(*elts)[elts_n] = rxq->elts;unsigned int i; -/* For each WR (packet). */ +assert (rte_is_power_of_2 (elts_n));for (i =0 ; i !=RTE_DIM (*elts); ++i) { -struct rxq_elt *elt = &(*elts)[i]; -struct ibv_recv_wr *wr = &elt->wr; -struct ibv_sge *sge = &(*elts)[i].sge; +volatile struct mlx4_wqe_data_seg *scat = &(*rxq->wqes)[i];struct rte_mbuf *buf =rte_pktmbuf_alloc (rxq->mp);if (buf ==NULL ) {while (i--) { -rte_pktmbuf_free_seg ((*elts)[i].buf); - (*elts)[i].buf =NULL ; +rte_pktmbuf_free_seg ((*elts)[i]); + (*elts)[i] =NULL ; } rte_errno =ENOMEM ;return -rte_errno; } - elt->buf = buf; - wr->next = &(*elts)[(i +1 )].wr; - wr->sg_list = sge; - wr->num_sge =1 ;/* Headroom is reserved by rte_pktmbuf_alloc(). */ assert (buf->data_off ==RTE_PKTMBUF_HEADROOM );/* Buffer is supposed to be empty. */ assert (rte_pktmbuf_data_len (buf) ==0 );assert (rte_pktmbuf_pkt_len (buf) ==0 ); -/* sge->addr must be able to store a pointer. */ -assert (sizeof (sge->addr) >=sizeof (uintptr_t )); -/* SGE keeps its headroom. */ - sge->addr = (uintptr_t ) - ((uint8_t *)buf->buf_addr +RTE_PKTMBUF_HEADROOM ); - sge->length = (buf->buf_len -RTE_PKTMBUF_HEADROOM ); - sge->lkey = rxq->mr->lkey; -/* Redundant check for tailroom. */ -assert (sge->length ==rte_pktmbuf_tailroom (buf)); +/* Only the first segment keeps headroom. */ +if (i % sges_n) + buf->data_off =0 ; + buf->port = rxq->port_id; + buf->data_len =rte_pktmbuf_tailroom (buf); + buf->pkt_len =rte_pktmbuf_tailroom (buf); + buf->nb_segs =1 ; + *scat = (struct mlx4_wqe_data_seg ){ + .addr =rte_cpu_to_be_64 (rte_pktmbuf_mtod (buf, + uintptr_t)), + .byte_count =rte_cpu_to_be_32 (buf->data_len), + .lkey =rte_cpu_to_be_32 (rxq->mr->lkey), + }; + (*elts)[i] = buf; } -/* The last WR pointer must be NULL. */ - (*elts)[(i -1 )].wr.next =NULL ; +DEBUG ("%p: allocated and configured %u segments (max %u packets)" , + (void *)rxq, elts_n, elts_n / sges_n);return 0 ; }
@@ -364,14 +366,14 @@ static void mlx4_rxq_free_elts(struct rxq *rxq) {unsigned int i; -struct rxq_elt (*elts)[rxq->elts_n] = rxq->elts; +struct rte_mbuf *(*elts)[1 << rxq->elts_n] = rxq->elts; -DEBUG ("%p: freeing WRs" , (void *)rxq); +DEBUG ("%p: freeing Rx queue elements" , (void *)rxq);for (i =0 ; (i !=RTE_DIM (*elts)); ++i) { -if (!(*elts)[i].buf) +if (!(*elts)[i])continue ; -rte_pktmbuf_free_seg ((*elts)[i].buf); - (*elts)[i].buf =NULL ; +rte_pktmbuf_free_seg ((*elts)[i]); + (*elts)[i] =NULL ; } }
@@ -400,8 +402,11 @@ mlx4_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, struct rte_mempool *mp) {struct priv *priv = dev->data->dev_private; +struct mlx4dv_obj mlxdv; +struct mlx4dv_rwq dv_rwq; +struct mlx4dv_cq dv_cq;uint32_t mb_len =rte_pktmbuf_data_room_size (mp); -struct rxq_elt (*elts)[desc]; +struct rte_mbuf *(*elts)[rte_align32pow2 (desc)];struct rte_flow_error error;struct rxq *rxq;struct rte_malloc_vec vec[] = {
@@ -439,6 +444,12 @@ mlx4_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,ERROR ("%p: invalid number of Rx descriptors" , (void *)dev);return -rte_errno; } +if (desc !=RTE_DIM (*elts)) { + desc =RTE_DIM (*elts); +WARN ("%p: increased number of descriptors in Rx queue %u" +" to the next power of two (%u)" , + (void *)dev, idx, desc); + }/* Allocate and initialize Rx queue. */ rte_zmallocv_socket ("RXQ" , vec,RTE_DIM (vec), socket);if (!rxq) {
@@ -450,8 +461,8 @@ mlx4_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, .priv = priv, .mp = mp, .port_id = dev->data->port_id, - .elts_n = desc, - .elts_head = 0, + .sges_n = 0, + .elts_n = rte_log2_u32(desc), .elts = elts, .stats.idx = idx, .socket = socket,
@@ -462,9 +473,29 @@ mlx4_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, (mb_len - RTE_PKTMBUF_HEADROOM)) { ; } else if (dev->data->dev_conf.rxmode.enable_scatter) { -WARN ("%p: scattered mode has been requested but is" -" not supported, this may lead to packet loss" , - (void *)dev); +uint32_t size = +RTE_PKTMBUF_HEADROOM + + dev->data->dev_conf.rxmode.max_rx_pkt_len; +uint32_t sges_n; + +/* +* Determine the number of SGEs needed for a full packet +* and round it to the next power of two. +*/ + sges_n =rte_log2_u32 ((size / mb_len) + !!(size % mb_len)); + rxq->sges_n = sges_n; +/* Make sure sges_n did not overflow. */ + size = mb_len * (1 << rxq->sges_n); + size -=RTE_PKTMBUF_HEADROOM ; +if (size < dev->data->dev_conf.rxmode.max_rx_pkt_len) { + rte_errno =EOVERFLOW ; +ERROR ("%p: too many SGEs (%u) needed to handle" +" requested maximum packet size %u" , + (void *)dev, +1 << sges_n, + dev->data->dev_conf.rxmode.max_rx_pkt_len); + goto error; + } } else {WARN ("%p: the requested maximum Rx packet size (%u) is" " larger than a single mbuf (%u) and scattered"
@@ -473,6 +504,17 @@ mlx4_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, dev->data->dev_conf.rxmode.max_rx_pkt_len, mb_len - RTE_PKTMBUF_HEADROOM); } +DEBUG ("%p: maximum number of segments per packet: %u" , + (void *)dev,1 << rxq->sges_n); +if (desc % (1 << rxq->sges_n)) { + rte_errno =EINVAL ; +ERROR ("%p: number of Rx queue descriptors (%u) is not a" +" multiple of maximum segments per packet (%u)" , + (void *)dev, + desc, +1 << rxq->sges_n); + goto error; + }/* Use the entire Rx mempool as the memory region. */ rxq->mr =mlx4_mp2mr (priv->pd, mp);if (!rxq->mr) {
@@ -497,7 +539,8 @@ mlx4_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, goto error; } } - rxq->cq =ibv_create_cq (priv->ctx, desc,NULL , rxq->channel,0 ); + rxq->cq =ibv_create_cq (priv->ctx, desc >> rxq->sges_n,NULL , + rxq->channel,0 );if (!rxq->cq) { rte_errno =ENOMEM ; ERROR("%p: CQ creation failure: %s",
@@ -508,8 +551,8 @@ mlx4_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, (priv->ctx, &(struct ibv_wq_init_attr ){ .wq_type =IBV_WQT_RQ , - .max_wr =RTE_MIN (priv->device_attr.max_qp_wr, desc), - .max_sge =1 , + .max_wr = desc >> rxq->sges_n, + .max_sge =1 << rxq->sges_n, .pd = priv->pd, .cq = rxq->cq, });
@@ -531,27 +574,43 @@ mlx4_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, (void *)dev, strerror(rte_errno)); goto error; } - ret =mlx4_rxq_alloc_elts (rxq); +/* Retrieve device queue information. */ + mlxdv.cq.in = rxq->cq; + mlxdv.cq.out = &dv_cq; + mlxdv.rwq.in = rxq->wq; + mlxdv.rwq.out = &dv_rwq; + ret =mlx4dv_init_obj (&mlxdv,MLX4DV_OBJ_RWQ |MLX4DV_OBJ_CQ );if (ret) { -ERROR ("%p: RXQ allocation failed: %s" , - (void *)dev,strerror (rte_errno)); + rte_errno =EINVAL ; +ERROR ("%p: failed to obtain device information" , (void *)dev); goto error; } - ret =ibv_post_wq_recv (rxq->wq, &(*rxq->elts)[0 ].wr, - &(struct ibv_recv_wr *){NULL }); + rxq->wqes = + (volatile struct mlx4_wqe_data_seg (*)[]) + ((uintptr_t )dv_rwq.buf.buf + dv_rwq.rq.offset); + rxq->rq_db = dv_rwq.rdb; + rxq->rq_ci =0 ; + rxq->mcq.buf = dv_cq.buf.buf; + rxq->mcq.cqe_cnt = dv_cq.cqe_cnt; + rxq->mcq.set_ci_db = dv_cq.set_ci_db; + rxq->mcq.cqe_64 = (dv_cq.cqe_size &64 ) ?1 :0 ; + ret =mlx4_rxq_alloc_elts (rxq);if (ret) { - rte_errno = ret; -ERROR ("%p: ibv_post_recv() failed: %s" , - (void *)dev, -strerror (rte_errno)); +ERROR ("%p: RXQ allocation failed: %s" , + (void *)dev,strerror (rte_errno)); goto error; }DEBUG ("%p: adding Rx queue %p to list" , (void *)dev, (void *)rxq); dev->data->rx_queues[idx] = rxq;/* Enable associated flows. */ ret =mlx4_flow_sync (priv, &error); -if (!ret) +if (!ret) { +/* Update doorbell counter. */ + rxq->rq_ci = desc >> rxq->sges_n; +rte_wmb (); + *rxq->rq_db =rte_cpu_to_be_32 (rxq->rq_ci);return 0 ; + } ERROR("cannot re-attach flow rules to queue %u" " (code %d, \"%s\"), flow error type %d, cause %p, message: %s", idx, -ret, strerror(-ret), error.type, error.cause,
drivers/net/mlx4/mlx4_rxtx.c +128 -98
249 lines not on this page · raw message
drivers/net/mlx4/mlx4_rxtx.h +8 -11
@@ -63,13 +63,6 @@ struct mlx4_rxq_stats {uint64_t rx_nombuf;/**< Total of Rx mbuf allocation failures. */ }; -/** Rx element. */ -struct rxq_elt { -struct ibv_recv_wr wr;/**< Work request. */ -struct ibv_sge sge;/**< Scatter/gather element. */ -struct rte_mbuf *buf;/**< Buffer. */ -}; -/** Rx queue descriptor. */ struct rxq {struct priv *priv;/**< Back pointer to private data. */
@@ -78,10 +71,14 @@ struct rxq {struct ibv_cq *cq;/**< Completion queue. */ struct ibv_wq *wq;/**< Work queue. */ struct ibv_comp_channel *channel;/**< Rx completion channel. */ -unsigned int port_id;/**< Port ID for incoming packets. */ -unsigned int elts_n;/**< (*elts)[] length. */ -unsigned int elts_head;/**< Current index in (*elts)[]. */ -struct rxq_elt (*elts)[];/**< Rx elements. */ +uint16_t rq_ci;/**< Saved RQ consumer index. */ +uint16_t port_id;/**< Port ID for incoming packets. */ +uint16_t sges_n;/**< Number of segments per packet (log2 value). */ +uint16_t elts_n;/**< Mbuf queue size (log2 value). */ +struct rte_mbuf *(*elts)[];/**< Rx elements. */ +volatile struct mlx4_wqe_data_seg (*wqes)[];/**< HW queue entries. */ +volatile uint32_t *rq_db;/**< RQ doorbell record. */ +struct mlx4_cq mcq;/**< Info for directly manipulating the CQ. */ struct mlx4_rxq_stats stats;/**< Rx queue counters. */ unsigned int socket;/**< CPU socket ID for allocations. */ uint8_t data[];/**< Remaining queue resources. */
Signature · 1 line
2.1.4
PATCH v5 3/5 net/mlx4: restore Tx checksum offloads
In reply to Adrien MazarguilFrom: Moti Haimovsky <[email protected]>
This patch adds hardware offloading support for IPv4, UDP and TCP checksum calculation, including inner/outer checksums on supported tunnel types.
--- drivers/net/mlx4/mlx4.c | 11 +++++++++++ drivers/net/mlx4/mlx4.h | 2 ++ drivers/net/mlx4/mlx4_ethdev.c | 6 ++++++ drivers/net/mlx4/mlx4_prm.h | 2 ++ drivers/net/mlx4/mlx4_rxtx.c | 19 +++++++++++++++++++ drivers/net/mlx4/mlx4_rxtx.h | 2 ++ drivers/net/mlx4/mlx4_txq.c | 2 ++ 7 files changed, 44 insertions(+)
drivers/net/mlx4/mlx4.c +11 -0
@@ -566,6 +566,17 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) priv->pd = pd; priv->mtu =ETHER_MTU ; priv->vf = vf; + priv->hw_csum = !!(device_attr.device_cap_flags & +IBV_DEVICE_RAW_IP_CSUM ); +DEBUG ("checksum offloading is %ssupported" , + (priv->hw_csum ?"" :"not " )); +/* Only ConnectX-3 Pro supports tunneling. */ + priv->hw_csum_l2tun = + priv->hw_csum && + (device_attr.vendor_part_id == +PCI_DEVICE_ID_MELLANOX_CONNECTX3PRO ); +DEBUG ("L2 tunnel checksum offloads are %ssupported" , + (priv->hw_csum_l2tun ?"" :"not " ));/* Configure the first MAC address by default. */ if (mlx4_get_mac (priv, &mac.addr_bytes)) { ERROR("cannot get MAC address, is mlx4_en loaded?"
drivers/net/mlx4/mlx4.h +2 -0
@@ -113,6 +113,8 @@ struct priv { uint32_t vf:1; /**< This is a VF device. */ uint32_t intr_alarm:1; /**< An interrupt alarm is scheduled. */ uint32_t isolated:1; /**< Toggle isolated mode. */ + uint32_t hw_csum:1; /* Checksum offload is supported. */ + uint32_t hw_csum_l2tun:1; /* Checksum support for L2 tunnels. */struct rte_intr_handle intr_handle;/**< Port interrupt handle. */ struct mlx4_drop *drop;/**< Shared resources for drop flow rules. */ LIST_HEAD(, mlx4_rss) rss; /**< Shared targets for Rx flow rules. */
drivers/net/mlx4/mlx4_ethdev.c +6 -0
@@ -767,6 +767,12 @@ mlx4_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) info->max_mac_addrs =RTE_DIM (priv->mac); info->rx_offload_capa =0 ; info->tx_offload_capa =0 ; +if (priv->hw_csum) + info->tx_offload_capa |= (DEV_TX_OFFLOAD_IPV4_CKSUM | +DEV_TX_OFFLOAD_UDP_CKSUM | +DEV_TX_OFFLOAD_TCP_CKSUM ); +if (priv->hw_csum_l2tun) + info->tx_offload_capa |=DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM ;if (mlx4_get_ifname (priv, &ifname) ==0 ) info->if_index =if_nametoindex (ifname); info->hash_key_size =MLX4_RSS_HASH_KEY_SIZE ;
drivers/net/mlx4/mlx4_prm.h +2 -0
@@ -64,6 +64,8 @@/* Work queue element (WQE) flags. */ #define MLX4_BIT_WQE_OWN 0x80000000 +#define MLX4_WQE_CTRL_IIP_HDR_CSUM (1 << 28) +#define MLX4_WQE_CTRL_IL4_HDR_CSUM (1 << 27)#define MLX4_SIZE_TO_TXBBS (size) \ (RTE_ALIGN((size), (MLX4_TXBB_SIZE)) >> (MLX4_TXBB_SHIFT))
drivers/net/mlx4/mlx4_rxtx.c +19 -0
@@ -431,6 +431,25 @@ mlx4_post_send(struct txq *txq, struct rte_mbuf *pkt) }else { srcrb_flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT ); } +/* Enable HW checksum offload if requested */ +if (txq->csum && + (pkt->ol_flags & + (PKT_TX_IP_CKSUM |PKT_TX_TCP_CKSUM |PKT_TX_UDP_CKSUM ))) { +const uint64_t is_tunneled = (pkt->ol_flags & + (PKT_TX_TUNNEL_GRE | +PKT_TX_TUNNEL_VXLAN )); + +if (is_tunneled && txq->csum_l2tun) { + owner_opcode |=MLX4_WQE_CTRL_IIP_HDR_CSUM | +MLX4_WQE_CTRL_IL4_HDR_CSUM ; +if (pkt->ol_flags &PKT_TX_OUTER_IP_CKSUM ) + srcrb_flags |= +RTE_BE32 (MLX4_WQE_CTRL_IP_HDR_CSUM ); + }else { + srcrb_flags |=RTE_BE32 (MLX4_WQE_CTRL_IP_HDR_CSUM | +MLX4_WQE_CTRL_TCP_UDP_CSUM ); + } + } ctrl->srcrb_flags = srcrb_flags;/* * Make sure descriptor is fully written before
drivers/net/mlx4/mlx4_rxtx.h +2 -0
@@ -124,6 +124,8 @@ struct txq {struct txq_elt (*elts)[];/**< Tx elements. */ struct mlx4_txq_stats stats;/**< Tx queue counters. */ uint32_t max_inline;/**< Max inline send size. */ + uint32_t csum:1; /**< Enable checksum offloading. */ + uint32_t csum_l2tun:1; /**< Same for L2 tunnels. */uint8_t *bounce_buf;/**< Memory used for storing the first DWORD of data TXBBs. */ struct {
drivers/net/mlx4/mlx4_txq.c +2 -0
@@ -276,6 +276,8 @@ mlx4_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, RTE_MIN(MLX4_PMD_TX_PER_COMP_REQ, desc / 4), .elts_comp_cd_init = RTE_MIN(MLX4_PMD_TX_PER_COMP_REQ, desc / 4), + .csum = priv->hw_csum, + .csum_l2tun = priv->hw_csum_l2tun, .bounce_buf = bounce_buf, }; txq->cq =ibv_create_cq (priv->ctx, desc,NULL ,NULL ,0 );
Signature · 1 line
2.1.4
PATCH v5 4/5 net/mlx4: restore Rx offloads
In reply to Adrien MazarguilFrom: Moti Haimovsky <[email protected]>
This patch adds hardware offloading support for IPV4, UDP and TCP checksum verification, including inner/outer checksums on supported tunnel types.
It also restores packet type recognition support.
--- drivers/net/mlx4/mlx4_ethdev.c | 6 +- drivers/net/mlx4/mlx4_prm.h | 29 +++++++++ drivers/net/mlx4/mlx4_rxq.c | 5 ++ drivers/net/mlx4/mlx4_rxtx.c | 118 +++++++++++++++++++++++++++++++++++- drivers/net/mlx4/mlx4_rxtx.h | 2 + 5 files changed, 157 insertions(+), 3 deletions(-)
drivers/net/mlx4/mlx4_ethdev.c +5 -1
@@ -767,10 +767,14 @@ mlx4_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) info->max_mac_addrs =RTE_DIM (priv->mac); info->rx_offload_capa =0 ; info->tx_offload_capa =0 ; -if (priv->hw_csum) +if (priv->hw_csum) { info->tx_offload_capa |= (DEV_TX_OFFLOAD_IPV4_CKSUM |DEV_TX_OFFLOAD_UDP_CKSUM |DEV_TX_OFFLOAD_TCP_CKSUM ); + info->rx_offload_capa |= (DEV_RX_OFFLOAD_IPV4_CKSUM | +DEV_RX_OFFLOAD_UDP_CKSUM | +DEV_RX_OFFLOAD_TCP_CKSUM ); + }if (priv->hw_csum_l2tun) info->tx_offload_capa |=DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM ;if (mlx4_get_ifname (priv, &ifname) ==0 )
drivers/net/mlx4/mlx4_prm.h +29 -0
@@ -70,6 +70,14 @@#define MLX4_SIZE_TO_TXBBS (size) \ (RTE_ALIGN((size), (MLX4_TXBB_SIZE)) >> (MLX4_TXBB_SHIFT)) +/* CQE checksum flags. */ +enum { +MLX4_CQE_L2_TUNNEL_IPV4 = (int )(1u <<25 ), +MLX4_CQE_L2_TUNNEL_L4_CSUM = (int )(1u <<26 ), +MLX4_CQE_L2_TUNNEL = (int )(1u <<27 ), +MLX4_CQE_L2_TUNNEL_IPOK = (int )(1u <<31 ), +}; +/* Send queue information. */ struct mlx4_sq {uint8_t *buf;/**< SQ buffer. */
@@ -119,4 +127,25 @@ mlx4_get_cqe(struct mlx4_cq *cq, uint32_t index) (cq->cqe_64 << 5)); } +/** +* Transpose a flag in a value. +* +* @param val +* Input value. +* @param from +* Flag to retrieve from input value. +* @param to +* Flag to set in output value. +* +* @return +* Output value with transposed flag enabled if present on input. +*/ +static inline uint64_t +mlx4_transpose (uint64_t val,uint64_t from,uint64_t to) +{ +return (from >= to ? + (val & from) / (from / to) : + (val & from) * (to / from)); +} +#endif /* MLX4_PRM_H_ */
drivers/net/mlx4/mlx4_rxq.c +5 -0
@@ -464,6 +464,11 @@ mlx4_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, .sges_n = 0, .elts_n = rte_log2_u32(desc), .elts = elts, +/* Toggle Rx checksum offload if hardware supports it. */ + .csum = (priv->hw_csum && + dev->data->dev_conf.rxmode.hw_ip_checksum), + .csum_l2tun = (priv->hw_csum_l2tun && + dev->data->dev_conf.rxmode.hw_ip_checksum), .stats.idx = idx, .socket = socket, };
drivers/net/mlx4/mlx4_rxtx.c +116 -2
130 lines not on this page · raw message
drivers/net/mlx4/mlx4_rxtx.h +2 -0
@@ -78,6 +78,8 @@ struct rxq {struct rte_mbuf *(*elts)[];/**< Rx elements. */ volatile struct mlx4_wqe_data_seg (*wqes)[];/**< HW queue entries. */ volatile uint32_t *rq_db;/**< RQ doorbell record. */ + uint32_t csum:1; /**< Enable checksum offloading. */ + uint32_t csum_l2tun:1; /**< Same for L2 tunnels. */struct mlx4_cq mcq;/**< Info for directly manipulating the CQ. */ struct mlx4_rxq_stats stats;/**< Rx queue counters. */ unsigned int socket;/**< CPU socket ID for allocations. */
Signature · 1 line
2.1.4
PATCH v5 5/5 net/mlx4: add loopback Tx from VF
In reply to Adrien MazarguilFrom: Moti Haimovsky <[email protected]>
This patch adds loopback functionality used when the chip is a VF in order to enable packet transmission between VFs and PF.
--- drivers/net/mlx4/mlx4_rxtx.c | 33 +++++++++++++++++++++------------ drivers/net/mlx4/mlx4_rxtx.h | 1 + drivers/net/mlx4/mlx4_txq.c | 2 ++ 3 files changed, 24 insertions(+), 12 deletions(-)
drivers/net/mlx4/mlx4_rxtx.c +21 -12
@@ -311,10 +311,13 @@ mlx4_post_send(struct txq *txq, struct rte_mbuf *pkt)struct mlx4_wqe_data_seg *dseg;struct mlx4_sq *sq = &txq->msq;struct rte_mbuf *buf; +union { +uint32_t flags; +uint16_t flags16[2 ]; + } srcrb;uint32_t head_idx = sq->head & sq->txbb_cnt_mask;uint32_t lkey;uintptr_t addr; -uint32_t srcrb_flags;uint32_t owner_opcode =MLX4_OPCODE_SEND ;uint32_t byte_count;int wqe_real_size;
@@ -414,22 +417,16 @@ mlx4_post_send(struct txq *txq, struct rte_mbuf *pkt)/* Fill the control parameters for this packet. */ ctrl->fence_size = (wqe_real_size >>4 ) &0x3f ;/* -* The caller should prepare "imm" in advance in order to support -* VF to VF communication (when the device is a virtual-function -* device (VF)). -*/ - ctrl->imm =0 ; -/* * For raw Ethernet, the SOLICIT flag is used to indicate that no ICRC * should be calculated. */ txq->elts_comp_cd -= nr_txbbs;if (unlikely (txq->elts_comp_cd <=0 )) { txq->elts_comp_cd = txq->elts_comp_cd_init; - srcrb_flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT | + srcrb.flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT |MLX4_WQE_CTRL_CQ_UPDATE ); }else { - srcrb_flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT ); + srcrb.flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT ); }/* Enable HW checksum offload if requested */ if (txq->csum &&
@@ -443,14 +440,26 @@ mlx4_post_send(struct txq *txq, struct rte_mbuf *pkt) owner_opcode |=MLX4_WQE_CTRL_IIP_HDR_CSUM |MLX4_WQE_CTRL_IL4_HDR_CSUM ;if (pkt->ol_flags &PKT_TX_OUTER_IP_CKSUM ) - srcrb_flags |= + srcrb.flags |=RTE_BE32 (MLX4_WQE_CTRL_IP_HDR_CSUM ); }else { - srcrb_flags |=RTE_BE32 (MLX4_WQE_CTRL_IP_HDR_CSUM | + srcrb.flags |=RTE_BE32 (MLX4_WQE_CTRL_IP_HDR_CSUM |MLX4_WQE_CTRL_TCP_UDP_CSUM ); } } - ctrl->srcrb_flags = srcrb_flags; +if (txq->lb) { +/* +* Copy destination MAC address to the WQE, this allows +* loopback in eSwitch, so that VFs and PF can communicate +* with each other. +*/ + srcrb.flags16[0] = *(rte_pktmbuf_mtod(pkt, uint16_t *)); + ctrl->imm = *(rte_pktmbuf_mtod_offset (pkt ,uint32_t *, + sizeof(uint16_t))); + }else { + ctrl->imm =0 ; + } + ctrl->srcrb_flags = srcrb.flags;/* * Make sure descriptor is fully written before * setting ownership bit (because HW can start
drivers/net/mlx4/mlx4_rxtx.h +1 -0
@@ -128,6 +128,7 @@ struct txq {uint32_t max_inline;/**< Max inline send size. */ uint32_t csum:1; /**< Enable checksum offloading. */ uint32_t csum_l2tun:1; /**< Same for L2 tunnels. */ + uint32_t lb:1; /**< Whether packets should be looped back by eSwitch. */uint8_t *bounce_buf;/**< Memory used for storing the first DWORD of data TXBBs. */ struct {
drivers/net/mlx4/mlx4_txq.c +2 -0
@@ -278,6 +278,8 @@ mlx4_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, RTE_MIN(MLX4_PMD_TX_PER_COMP_REQ, desc / 4), .csum = priv->hw_csum, .csum_l2tun = priv->hw_csum_l2tun, +/* Enable Tx loopback for VF devices. */ + .lb = !!priv->vf, .bounce_buf = bounce_buf, }; txq->cq =ibv_create_cq (priv->ctx, desc,NULL ,NULL ,0 );
Signature · 1 line
2.1.4
v6 cover new mlx4 datapath bypassing ibverbs
In reply to Adrien MazarguilHopefully the last iteration for this series.
v6 (Adrien):
- Updated features documentation (mlx4.ini) in the relevant patches.
- Rebased on the latest changes brought by RSS support v2 series.
v5 (Ophir & Adrien):
- Merged Rx scatter/Tx gather code back into individual Rx/Tx commits for consistency due to a couple of issues with gather-less Tx.
- Rebased on top of the latest mlx4 control path changes (RSS support).
v4 (Ophir):
- Split "net/mlx4: restore Rx scatter support" commit from "net/mlx4:
restore full Rx support bypassing Verbs" commit
v3 (Adrien):
- Drop a few unrelated or unnecessary changes such as the removal of MLX4_PMD_TX_MP_CACHE.
- Move device checksum support detection code to its previous location.
- Fix include guard in mlx4_prm.h.
- Reorder #includes alphabetically.
- Replace MLX4_TRANSPOSE() macro with documented inline function.
- Remove extra spaces and blank lines.
- Use uint8_t * instead of char * for buffers.
- Replace mlx4_get_cqe() macro with a documented inline function.
- Replace several unsigned int with uint32_t.
- Add consistency to field names (sge_n => sges_n).
- Make mbuf size checks in RX queue setup function similar to mlx5.
- Update various comments.
- Fix indentation.
- Replace run-time endian conversion with static ones where possible.
- Reorder fields in struct rxq and struct txq for consistency, remove one level of unnecessary inner structures.
- Fix memory leak on Tx bounce buffer.
- Update commit logs.
- Fix remaining checkpatch warnings.
v2 (Matan):
Rearange patches.
Semantics.
Enhancements.
Fix compilation issues.
Moti Haimovsky (5):
net/mlx4: add Tx bypassing Verbs
net/mlx4: add Rx bypassing Verbs
net/mlx4: restore Tx checksum offloads
net/mlx4: restore Rx offloads
net/mlx4: add loopback Tx from VF
doc/guides/nics/features/mlx4.ini | 6 + drivers/net/mlx4/mlx4.c | 11 + drivers/net/mlx4/mlx4.h | 2 + drivers/net/mlx4/mlx4_ethdev.c | 10 + drivers/net/mlx4/mlx4_prm.h | 151 +++++++ drivers/net/mlx4/mlx4_rxq.c | 156 +++++-- drivers/net/mlx4/mlx4_rxtx.c | 768 ++++++++++++++++++++++++--------- drivers/net/mlx4/mlx4_rxtx.h | 54 +-- drivers/net/mlx4/mlx4_txq.c | 63 +++ 9 files changed, 948 insertions(+), 273 deletions(-) create mode 100644 drivers/net/mlx4/mlx4_prm.h
Signature · 1 line
2.1.4
PATCH v6 1/5 net/mlx4: add Tx bypassing Verbs
From: Moti Haimovsky <[email protected]>
Modify PMD to send single-buffer packets directly to the device bypassing the Verbs Tx post and poll routines.
Tx gather support: add support for transmitting packets spanning over multiple buffers.
Take into consideration the amount of entries a packet occupies in the TxQ when setting the report-completion flag of the chip.
--- drivers/net/mlx4/mlx4_prm.h | 120 ++++++++++++ drivers/net/mlx4/mlx4_rxtx.c | 398 ++++++++++++++++++++++++++++---------- drivers/net/mlx4/mlx4_rxtx.h | 30 +-- drivers/net/mlx4/mlx4_txq.c | 59 ++++++ 4 files changed, 490 insertions(+), 117 deletions(-)
drivers/net/mlx4/mlx4_prm.h new file +120 -0
@@ -0,0 +1,120 @@ +/*- +* BSD LICENSE +* +* Copyright 2017 6WIND S.A. +* Copyright 2017 Mellanox +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of 6WIND S.A. nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef MLX4_PRM_H_ +#define MLX4_PRM_H_ + +#include <rte_atomic.h> +#include <rte_branch_prediction.h> +#include <rte_byteorder.h> + +/* Verbs headers do not support -pedantic. */ +#ifdef PEDANTIC +#pragma GCC diagnostic ignored "-Wpedantic" +#endif +#include <infiniband/mlx4dv.h> +#include <infiniband/verbs.h> +#ifdef PEDANTIC +#pragma GCC diagnostic error "-Wpedantic" +#endif + +/* ConnectX-3 Tx queue basic block. */ +#define MLX4_TXBB_SHIFT 6 +#define MLX4_TXBB_SIZE (1 << MLX4_TXBB_SHIFT) + +/* Typical TSO descriptor with 16 gather entries is 352 bytes. */ +#define MLX4_MAX_WQE_SIZE 512 +#define MLX4_MAX_WQE_TXBBS (MLX4_MAX_WQE_SIZE / MLX4_TXBB_SIZE) + +/* Send queue stamping/invalidating information. */ +#define MLX4_SQ_STAMP_STRIDE 64 +#define MLX4_SQ_STAMP_DWORDS (MLX4_SQ_STAMP_STRIDE / 4) +#define MLX4_SQ_STAMP_SHIFT 31 +#define MLX4_SQ_STAMP_VAL 0x7fffffff + +/* Work queue element (WQE) flags. */ +#define MLX4_BIT_WQE_OWN 0x80000000 + +#define MLX4_SIZE_TO_TXBBS (size) \ + (RTE_ALIGN((size), (MLX4_TXBB_SIZE)) >> (MLX4_TXBB_SHIFT)) + +/* Send queue information. */ +struct mlx4_sq { +uint8_t *buf;/**< SQ buffer. */ +uint8_t *eob;/**< End of SQ buffer */ +uint32_t head;/**< SQ head counter in units of TXBBS. */ +uint32_t tail;/**< SQ tail counter in units of TXBBS. */ +uint32_t txbb_cnt;/**< Num of WQEBB in the Q (should be ^2). */ +uint32_t txbb_cnt_mask;/**< txbbs_cnt mask (txbb_cnt is ^2). */ +uint32_t headroom_txbbs;/**< Num of txbbs that should be kept free. */ +uint32_t *db;/**< Pointer to the doorbell. */ +uint32_t doorbell_qpn;/**< qp number to write to the doorbell. */ +}; + +#define mlx4_get_send_wqe (sq, n) ((sq)->buf + ((n) * (MLX4_TXBB_SIZE))) + +/* Completion queue information. */ +struct mlx4_cq { +uint8_t *buf;/**< Pointer to the completion queue buffer. */ +uint32_t cqe_cnt;/**< Number of entries in the queue. */ +uint32_t cqe_64:1 ;/**< CQ entry size is 64 bytes. */ +uint32_t cons_index;/**< Last queue entry that was handled. */ +uint32_t *set_ci_db;/**< Pointer to the completion queue doorbell. */ +}; + +/** +* Retrieve a CQE entry from a CQ. +* +* cqe = cq->buf + cons_index * cqe_size + cqe_offset +* +* Where cqe_size is 32 or 64 bytes and cqe_offset is 0 or 32 (depending on +* cqe_size). +* +* @param cq +* CQ to retrieve entry from. +* @param index +* Entry index. +* +* @return +* Pointer to CQE entry. +*/ +static inline struct mlx4_cqe * +mlx4_get_cqe (struct mlx4_cq *cq,uint32_t index) +{ +return (struct mlx4_cqe *)(cq->buf + + ((index & (cq->cqe_cnt -1 )) << + (5 + cq->cqe_64)) + + (cq->cqe_64 <<5 )); +} + +#endif /* MLX4_PRM_H_ */
drivers/net/mlx4/mlx4_rxtx.c +294 -104
469 lines not on this page · raw message
drivers/net/mlx4/mlx4_rxtx.h +17 -13
@@ -41,6 +41,7 @@#ifdef PEDANTIC #pragma GCC diagnostic ignored "-Wpedantic"#endif +#include <infiniband/mlx4dv.h> #include <infiniband/verbs.h> #ifdef PEDANTIC #pragma GCC diagnostic error "-Wpedantic"
@@ -51,6 +52,7 @@#include <rte_mempool.h> #include "mlx4.h" +#include "mlx4_prm.h" /** Rx queue counters. */ struct mlx4_rxq_stats {
@@ -101,8 +103,6 @@ struct mlx4_rss {/** Tx element. */ struct txq_elt { -struct ibv_send_wr wr;/**< Work request. */ -struct ibv_sge sge;/**< Scatter/gather element. */ struct rte_mbuf *buf;/**< Buffer. */ };
@@ -116,24 +116,28 @@ struct mlx4_txq_stats {/** Tx queue descriptor. */ struct txq { -struct priv *priv;/**< Back pointer to private data. */ +struct mlx4_sq msq;/**< Info for directly manipulating the SQ. */ +struct mlx4_cq mcq;/**< Info for directly manipulating the CQ. */ +unsigned int elts_head;/**< Current index in (*elts)[]. */ +unsigned int elts_tail;/**< First element awaiting completion. */ +unsigned int elts_comp;/**< Number of packets awaiting completion. */ +int elts_comp_cd;/**< Countdown for next completion. */ +unsigned int elts_comp_cd_init;/**< Initial value for countdown. */ +unsigned int elts_n;/**< (*elts)[] length. */ +struct txq_elt (*elts)[];/**< Tx elements. */ +struct mlx4_txq_stats stats;/**< Tx queue counters. */ +uint32_t max_inline;/**< Max inline send size. */ +uint8_t *bounce_buf; +/**< Memory used for storing the first DWORD of data TXBBs. */ struct {const struct rte_mempool *mp;/**< Cached memory pool. */ struct ibv_mr *mr;/**< Memory region (for mp). */ uint32_t lkey;/**< mr->lkey copy. */ } mp2mr[MLX4_PMD_TX_MP_CACHE ];/**< MP to MR translation table. */ +struct priv *priv;/**< Back pointer to private data. */ +unsigned int socket;/**< CPU socket ID for allocations. */ struct ibv_cq *cq;/**< Completion queue. */ struct ibv_qp *qp;/**< Queue pair. */ -uint32_t max_inline;/**< Max inline send size. */ -unsigned int elts_n;/**< (*elts)[] length. */ -struct txq_elt (*elts)[];/**< Tx elements. */ -unsigned int elts_head;/**< Current index in (*elts)[]. */ -unsigned int elts_tail;/**< First element awaiting completion. */ -unsigned int elts_comp;/**< Number of completion requests. */ -unsigned int elts_comp_cd;/**< Countdown for next completion. */ -unsigned int elts_comp_cd_init;/**< Initial value for countdown. */ -struct mlx4_txq_stats stats;/**< Tx queue counters. */ -unsigned int socket;/**< CPU socket ID for allocations. */ uint8_t data[];/**< Remaining queue resources. */ };
drivers/net/mlx4/mlx4_txq.c +59 -0
98 lines not on this page · raw message
Signature · 1 line
2.1.4
PATCH v6 2/5 net/mlx4: add Rx bypassing Verbs
In reply to Adrien MazarguilFrom: Moti Haimovsky <[email protected]>
This patch adds support for accessing the hardware directly when handling Rx packets eliminating the need to use Verbs in the Rx data path.
Rx scatter support: calculate the number of scatters on the fly according to the maximum expected packet size.
--- doc/guides/nics/features/mlx4.ini | 1 + drivers/net/mlx4/mlx4_rxq.c | 151 +++++++++++++++------- drivers/net/mlx4/mlx4_rxtx.c | 226 +++++++++++++++++++-------------- drivers/net/mlx4/mlx4_rxtx.h | 19 ++- 4 files changed, 242 insertions(+), 155 deletions(-)
doc/guides/nics/features/mlx4.ini +1 -0
@@ -12,6 +12,7 @@ Rx interrupt = Y Queue start/stop = Y MTU update = Y Jumbo frame = Y +Scattered Rx = Y Promiscuous mode = Y Allmulticast mode = Y Unicast MAC filter = Y
drivers/net/mlx4/mlx4_rxq.c +105 -46
249 lines not on this page · raw message
drivers/net/mlx4/mlx4_rxtx.c +128 -98
249 lines not on this page · raw message
drivers/net/mlx4/mlx4_rxtx.h +8 -11
@@ -63,13 +63,6 @@ struct mlx4_rxq_stats {uint64_t rx_nombuf;/**< Total of Rx mbuf allocation failures. */ }; -/** Rx element. */ -struct rxq_elt { -struct ibv_recv_wr wr;/**< Work request. */ -struct ibv_sge sge;/**< Scatter/gather element. */ -struct rte_mbuf *buf;/**< Buffer. */ -}; -/** Rx queue descriptor. */ struct rxq {struct priv *priv;/**< Back pointer to private data. */
@@ -78,10 +71,14 @@ struct rxq {struct ibv_cq *cq;/**< Completion queue. */ struct ibv_wq *wq;/**< Work queue. */ struct ibv_comp_channel *channel;/**< Rx completion channel. */ -unsigned int port_id;/**< Port ID for incoming packets. */ -unsigned int elts_n;/**< (*elts)[] length. */ -unsigned int elts_head;/**< Current index in (*elts)[]. */ -struct rxq_elt (*elts)[];/**< Rx elements. */ +uint16_t rq_ci;/**< Saved RQ consumer index. */ +uint16_t port_id;/**< Port ID for incoming packets. */ +uint16_t sges_n;/**< Number of segments per packet (log2 value). */ +uint16_t elts_n;/**< Mbuf queue size (log2 value). */ +struct rte_mbuf *(*elts)[];/**< Rx elements. */ +volatile struct mlx4_wqe_data_seg (*wqes)[];/**< HW queue entries. */ +volatile uint32_t *rq_db;/**< RQ doorbell record. */ +struct mlx4_cq mcq;/**< Info for directly manipulating the CQ. */ struct mlx4_rxq_stats stats;/**< Rx queue counters. */ unsigned int socket;/**< CPU socket ID for allocations. */ uint8_t data[];/**< Remaining queue resources. */
Signature · 1 line
2.1.4
PATCH v6 3/5 net/mlx4: restore Tx checksum offloads
In reply to Adrien MazarguilFrom: Moti Haimovsky <[email protected]>
This patch adds hardware offloading support for IPv4, UDP and TCP checksum calculation, including inner/outer checksums on supported tunnel types.
--- doc/guides/nics/features/mlx4.ini | 4 ++++ drivers/net/mlx4/mlx4.c | 11 +++++++++++ drivers/net/mlx4/mlx4.h | 2 ++ drivers/net/mlx4/mlx4_ethdev.c | 6 ++++++ drivers/net/mlx4/mlx4_prm.h | 2 ++ drivers/net/mlx4/mlx4_rxtx.c | 19 +++++++++++++++++++ drivers/net/mlx4/mlx4_rxtx.h | 2 ++ drivers/net/mlx4/mlx4_txq.c | 2 ++ 8 files changed, 48 insertions(+)
doc/guides/nics/features/mlx4.ini +4 -0
@@ -20,6 +20,10 @@ Multicast MAC filter = Y RSS hash = Y SR-IOV = Y VLAN filter = Y +L3 checksum offload = Y +L4 checksum offload = Y +Inner L3 checksum = Y +Inner L4 checksum = Y Basic stats = Y Stats per queue = Y Other kdrv = Y
drivers/net/mlx4/mlx4.c +11 -0
@@ -566,6 +566,17 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) priv->pd = pd; priv->mtu =ETHER_MTU ; priv->vf = vf; + priv->hw_csum = !!(device_attr.device_cap_flags & +IBV_DEVICE_RAW_IP_CSUM ); +DEBUG ("checksum offloading is %ssupported" , + (priv->hw_csum ?"" :"not " )); +/* Only ConnectX-3 Pro supports tunneling. */ + priv->hw_csum_l2tun = + priv->hw_csum && + (device_attr.vendor_part_id == +PCI_DEVICE_ID_MELLANOX_CONNECTX3PRO ); +DEBUG ("L2 tunnel checksum offloads are %ssupported" , + (priv->hw_csum_l2tun ?"" :"not " ));/* Configure the first MAC address by default. */ if (mlx4_get_mac (priv, &mac.addr_bytes)) { ERROR("cannot get MAC address, is mlx4_en loaded?"
drivers/net/mlx4/mlx4.h +2 -0
@@ -113,6 +113,8 @@ struct priv { uint32_t vf:1; /**< This is a VF device. */ uint32_t intr_alarm:1; /**< An interrupt alarm is scheduled. */ uint32_t isolated:1; /**< Toggle isolated mode. */ + uint32_t hw_csum:1; /* Checksum offload is supported. */ + uint32_t hw_csum_l2tun:1; /* Checksum support for L2 tunnels. */struct rte_intr_handle intr_handle;/**< Port interrupt handle. */ struct mlx4_drop *drop;/**< Shared resources for drop flow rules. */ LIST_HEAD(, mlx4_rss) rss; /**< Shared targets for Rx flow rules. */
drivers/net/mlx4/mlx4_ethdev.c +6 -0
@@ -767,6 +767,12 @@ mlx4_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) info->max_mac_addrs =RTE_DIM (priv->mac); info->rx_offload_capa =0 ; info->tx_offload_capa =0 ; +if (priv->hw_csum) + info->tx_offload_capa |= (DEV_TX_OFFLOAD_IPV4_CKSUM | +DEV_TX_OFFLOAD_UDP_CKSUM | +DEV_TX_OFFLOAD_TCP_CKSUM ); +if (priv->hw_csum_l2tun) + info->tx_offload_capa |=DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM ;if (mlx4_get_ifname (priv, &ifname) ==0 ) info->if_index =if_nametoindex (ifname); info->hash_key_size =MLX4_RSS_HASH_KEY_SIZE ;
drivers/net/mlx4/mlx4_prm.h +2 -0
@@ -64,6 +64,8 @@/* Work queue element (WQE) flags. */ #define MLX4_BIT_WQE_OWN 0x80000000 +#define MLX4_WQE_CTRL_IIP_HDR_CSUM (1 << 28) +#define MLX4_WQE_CTRL_IL4_HDR_CSUM (1 << 27)#define MLX4_SIZE_TO_TXBBS (size) \ (RTE_ALIGN((size), (MLX4_TXBB_SIZE)) >> (MLX4_TXBB_SHIFT))
drivers/net/mlx4/mlx4_rxtx.c +19 -0
@@ -431,6 +431,25 @@ mlx4_post_send(struct txq *txq, struct rte_mbuf *pkt) }else { srcrb_flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT ); } +/* Enable HW checksum offload if requested */ +if (txq->csum && + (pkt->ol_flags & + (PKT_TX_IP_CKSUM |PKT_TX_TCP_CKSUM |PKT_TX_UDP_CKSUM ))) { +const uint64_t is_tunneled = (pkt->ol_flags & + (PKT_TX_TUNNEL_GRE | +PKT_TX_TUNNEL_VXLAN )); + +if (is_tunneled && txq->csum_l2tun) { + owner_opcode |=MLX4_WQE_CTRL_IIP_HDR_CSUM | +MLX4_WQE_CTRL_IL4_HDR_CSUM ; +if (pkt->ol_flags &PKT_TX_OUTER_IP_CKSUM ) + srcrb_flags |= +RTE_BE32 (MLX4_WQE_CTRL_IP_HDR_CSUM ); + }else { + srcrb_flags |=RTE_BE32 (MLX4_WQE_CTRL_IP_HDR_CSUM | +MLX4_WQE_CTRL_TCP_UDP_CSUM ); + } + } ctrl->srcrb_flags = srcrb_flags;/* * Make sure descriptor is fully written before
drivers/net/mlx4/mlx4_rxtx.h +2 -0
@@ -124,6 +124,8 @@ struct txq {struct txq_elt (*elts)[];/**< Tx elements. */ struct mlx4_txq_stats stats;/**< Tx queue counters. */ uint32_t max_inline;/**< Max inline send size. */ + uint32_t csum:1; /**< Enable checksum offloading. */ + uint32_t csum_l2tun:1; /**< Same for L2 tunnels. */uint8_t *bounce_buf;/**< Memory used for storing the first DWORD of data TXBBs. */ struct {
drivers/net/mlx4/mlx4_txq.c +2 -0
@@ -276,6 +276,8 @@ mlx4_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, RTE_MIN(MLX4_PMD_TX_PER_COMP_REQ, desc / 4), .elts_comp_cd_init = RTE_MIN(MLX4_PMD_TX_PER_COMP_REQ, desc / 4), + .csum = priv->hw_csum, + .csum_l2tun = priv->hw_csum_l2tun, .bounce_buf = bounce_buf, }; txq->cq =ibv_create_cq (priv->ctx, desc,NULL ,NULL ,0 );
Signature · 1 line
2.1.4
PATCH v6 4/5 net/mlx4: restore Rx offloads
In reply to Adrien MazarguilFrom: Moti Haimovsky <[email protected]>
This patch adds hardware offloading support for IPV4, UDP and TCP checksum verification, including inner/outer checksums on supported tunnel types.
It also restores packet type recognition support.
--- doc/guides/nics/features/mlx4.ini | 1 + drivers/net/mlx4/mlx4_ethdev.c | 6 +- drivers/net/mlx4/mlx4_prm.h | 29 ++++++++ drivers/net/mlx4/mlx4_rxq.c | 5 ++ drivers/net/mlx4/mlx4_rxtx.c | 118 ++++++++++++++++++++++++++++++++- drivers/net/mlx4/mlx4_rxtx.h | 2 + 6 files changed, 158 insertions(+), 3 deletions(-)
doc/guides/nics/features/mlx4.ini +1 -0
@@ -24,6 +24,7 @@ L3 checksum offload = Y L4 checksum offload = Y Inner L3 checksum = Y Inner L4 checksum = Y +Packet type parsing = Y Basic stats = Y Stats per queue = Y Other kdrv = Y
drivers/net/mlx4/mlx4_ethdev.c +5 -1
@@ -767,10 +767,14 @@ mlx4_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) info->max_mac_addrs =RTE_DIM (priv->mac); info->rx_offload_capa =0 ; info->tx_offload_capa =0 ; -if (priv->hw_csum) +if (priv->hw_csum) { info->tx_offload_capa |= (DEV_TX_OFFLOAD_IPV4_CKSUM |DEV_TX_OFFLOAD_UDP_CKSUM |DEV_TX_OFFLOAD_TCP_CKSUM ); + info->rx_offload_capa |= (DEV_RX_OFFLOAD_IPV4_CKSUM | +DEV_RX_OFFLOAD_UDP_CKSUM | +DEV_RX_OFFLOAD_TCP_CKSUM ); + }if (priv->hw_csum_l2tun) info->tx_offload_capa |=DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM ;if (mlx4_get_ifname (priv, &ifname) ==0 )
drivers/net/mlx4/mlx4_prm.h +29 -0
@@ -70,6 +70,14 @@#define MLX4_SIZE_TO_TXBBS (size) \ (RTE_ALIGN((size), (MLX4_TXBB_SIZE)) >> (MLX4_TXBB_SHIFT)) +/* CQE checksum flags. */ +enum { +MLX4_CQE_L2_TUNNEL_IPV4 = (int )(1u <<25 ), +MLX4_CQE_L2_TUNNEL_L4_CSUM = (int )(1u <<26 ), +MLX4_CQE_L2_TUNNEL = (int )(1u <<27 ), +MLX4_CQE_L2_TUNNEL_IPOK = (int )(1u <<31 ), +}; +/* Send queue information. */ struct mlx4_sq {uint8_t *buf;/**< SQ buffer. */
@@ -119,4 +127,25 @@ mlx4_get_cqe(struct mlx4_cq *cq, uint32_t index) (cq->cqe_64 << 5)); } +/** +* Transpose a flag in a value. +* +* @param val +* Input value. +* @param from +* Flag to retrieve from input value. +* @param to +* Flag to set in output value. +* +* @return +* Output value with transposed flag enabled if present on input. +*/ +static inline uint64_t +mlx4_transpose (uint64_t val,uint64_t from,uint64_t to) +{ +return (from >= to ? + (val & from) / (from / to) : + (val & from) * (to / from)); +} +#endif /* MLX4_PRM_H_ */
drivers/net/mlx4/mlx4_rxq.c +5 -0
@@ -464,6 +464,11 @@ mlx4_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, .sges_n = 0, .elts_n = rte_log2_u32(desc), .elts = elts, +/* Toggle Rx checksum offload if hardware supports it. */ + .csum = (priv->hw_csum && + dev->data->dev_conf.rxmode.hw_ip_checksum), + .csum_l2tun = (priv->hw_csum_l2tun && + dev->data->dev_conf.rxmode.hw_ip_checksum), .stats.idx = idx, .socket = socket, };
drivers/net/mlx4/mlx4_rxtx.c +116 -2
130 lines not on this page · raw message
drivers/net/mlx4/mlx4_rxtx.h +2 -0
@@ -78,6 +78,8 @@ struct rxq {struct rte_mbuf *(*elts)[];/**< Rx elements. */ volatile struct mlx4_wqe_data_seg (*wqes)[];/**< HW queue entries. */ volatile uint32_t *rq_db;/**< RQ doorbell record. */ + uint32_t csum:1; /**< Enable checksum offloading. */ + uint32_t csum_l2tun:1; /**< Same for L2 tunnels. */struct mlx4_cq mcq;/**< Info for directly manipulating the CQ. */ struct mlx4_rxq_stats stats;/**< Rx queue counters. */ unsigned int socket;/**< CPU socket ID for allocations. */
Signature · 1 line
2.1.4
PATCH v6 5/5 net/mlx4: add loopback Tx from VF
In reply to Adrien MazarguilFrom: Moti Haimovsky <[email protected]>
This patch adds loopback functionality used when the chip is a VF in order to enable packet transmission between VFs and PF.
--- drivers/net/mlx4/mlx4_rxtx.c | 33 +++++++++++++++++++++------------ drivers/net/mlx4/mlx4_rxtx.h | 1 + drivers/net/mlx4/mlx4_txq.c | 2 ++ 3 files changed, 24 insertions(+), 12 deletions(-)
drivers/net/mlx4/mlx4_rxtx.c +21 -12
@@ -311,10 +311,13 @@ mlx4_post_send(struct txq *txq, struct rte_mbuf *pkt)struct mlx4_wqe_data_seg *dseg;struct mlx4_sq *sq = &txq->msq;struct rte_mbuf *buf; +union { +uint32_t flags; +uint16_t flags16[2 ]; + } srcrb;uint32_t head_idx = sq->head & sq->txbb_cnt_mask;uint32_t lkey;uintptr_t addr; -uint32_t srcrb_flags;uint32_t owner_opcode =MLX4_OPCODE_SEND ;uint32_t byte_count;int wqe_real_size;
@@ -414,22 +417,16 @@ mlx4_post_send(struct txq *txq, struct rte_mbuf *pkt)/* Fill the control parameters for this packet. */ ctrl->fence_size = (wqe_real_size >>4 ) &0x3f ;/* -* The caller should prepare "imm" in advance in order to support -* VF to VF communication (when the device is a virtual-function -* device (VF)). -*/ - ctrl->imm =0 ; -/* * For raw Ethernet, the SOLICIT flag is used to indicate that no ICRC * should be calculated. */ txq->elts_comp_cd -= nr_txbbs;if (unlikely (txq->elts_comp_cd <=0 )) { txq->elts_comp_cd = txq->elts_comp_cd_init; - srcrb_flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT | + srcrb.flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT |MLX4_WQE_CTRL_CQ_UPDATE ); }else { - srcrb_flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT ); + srcrb.flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT ); }/* Enable HW checksum offload if requested */ if (txq->csum &&
@@ -443,14 +440,26 @@ mlx4_post_send(struct txq *txq, struct rte_mbuf *pkt) owner_opcode |=MLX4_WQE_CTRL_IIP_HDR_CSUM |MLX4_WQE_CTRL_IL4_HDR_CSUM ;if (pkt->ol_flags &PKT_TX_OUTER_IP_CKSUM ) - srcrb_flags |= + srcrb.flags |=RTE_BE32 (MLX4_WQE_CTRL_IP_HDR_CSUM ); }else { - srcrb_flags |=RTE_BE32 (MLX4_WQE_CTRL_IP_HDR_CSUM | + srcrb.flags |=RTE_BE32 (MLX4_WQE_CTRL_IP_HDR_CSUM |MLX4_WQE_CTRL_TCP_UDP_CSUM ); } } - ctrl->srcrb_flags = srcrb_flags; +if (txq->lb) { +/* +* Copy destination MAC address to the WQE, this allows +* loopback in eSwitch, so that VFs and PF can communicate +* with each other. +*/ + srcrb.flags16[0] = *(rte_pktmbuf_mtod(pkt, uint16_t *)); + ctrl->imm = *(rte_pktmbuf_mtod_offset (pkt ,uint32_t *, + sizeof(uint16_t))); + }else { + ctrl->imm =0 ; + } + ctrl->srcrb_flags = srcrb.flags;/* * Make sure descriptor is fully written before * setting ownership bit (because HW can start
drivers/net/mlx4/mlx4_rxtx.h +1 -0
@@ -128,6 +128,7 @@ struct txq {uint32_t max_inline;/**< Max inline send size. */ uint32_t csum:1; /**< Enable checksum offloading. */ uint32_t csum_l2tun:1; /**< Same for L2 tunnels. */ + uint32_t lb:1; /**< Whether packets should be looped back by eSwitch. */uint8_t *bounce_buf;/**< Memory used for storing the first DWORD of data TXBBs. */ struct {
drivers/net/mlx4/mlx4_txq.c +2 -0
@@ -278,6 +278,8 @@ mlx4_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, RTE_MIN(MLX4_PMD_TX_PER_COMP_REQ, desc / 4), .csum = priv->hw_csum, .csum_l2tun = priv->hw_csum_l2tun, +/* Enable Tx loopback for VF devices. */ + .lb = !!priv->vf, .bounce_buf = bounce_buf, }; txq->cq =ibv_create_cq (priv->ctx, desc,NULL ,NULL ,0 );
Signature · 1 line
2.1.4
Re: [PATCH v6 0/5] new mlx4 datapath bypassing ibverbs
In reply to Adrien MazarguilHi Adrien,
I am trying to compile mlx4 (and later to try mlx5) pmd in RHEL 7.4 (ppc64le) without Mellanox OFED, using current master (which has below patch series).
As I do so, I hit with below compile error:
dpdk/drivers/net/mlx4/mlx4.c:53:31: fatal error: infiniband/mlx4dv.h: No such file or directory #include <infiniband/mlx4dv.h>
^
compilation terminated.
make[6]: *** [mlx4.o] Error 1
I tried to find rpm for this directverbs include, but I could not. Could you advice if I have to install any additional rpm in RHEL 7.4 ? To note, I have rdma-core and libibverbs installed.
Thanks,
Gowrishankar
Quoted 62 lines · Adrien Mazarguil
Hopefully the last iteration for this series.
v6 (Adrien):
- Updated features documentation (mlx4.ini) in the relevant patches.
- Rebased on the latest changes brought by RSS support v2 series.v5 (Ophir & Adrien):
- Merged Rx scatter/Tx gather code back into individual Rx/Tx commits for consistency due to a couple of issues with gather-less Tx.
- Rebased on top of the latest mlx4 control path changes (RSS support).v4 (Ophir):
- Split "net/mlx4: restore Rx scatter support" commit from "net/mlx4:
restore full Rx support bypassing Verbs" commitv3 (Adrien):
- Drop a few unrelated or unnecessary changes such as the removal ofMLX4_PMD_TX_MP_CACHE.
- Move device checksum support detection code to its previous location.
- Fix include guard inmlx4_prm.h.
- Reorder #includes alphabetically.
- ReplaceMLX4_TRANSPOSE()macro with documented inline function.
- Remove extra spaces and blank lines.
- Useuint8_t* instead of char * for buffers.
- Replacemlx4_get_cqe()macro with a documented inline function.
- Replace several unsigned int withuint32_t.
- Add consistency to field names (sge_n=>sges_n).
- Make mbuf size checks in RX queue setup function similar to mlx5.
- Update various comments.
- Fix indentation.
- Replace run-time endian conversion with static ones where possible.
- Reorder fields in struct rxq and struct txq for consistency, remove one level of unnecessary inner structures.
- Fix memory leak on Tx bounce buffer.
- Update commit logs.
- Fix remaining checkpatch warnings.v2 (Matan):
Rearange patches.
Semantics.
Enhancements.
Fix compilation issues.Moti Haimovsky (5):
net/mlx4: add Tx bypassing Verbs
net/mlx4: add Rx bypassing Verbs
net/mlx4: restore Tx checksum offloads
net/mlx4: restore Rx offloads
net/mlx4: add loopback Tx from VFdoc/guides/nics/features/mlx4.ini | 6 + drivers/net/mlx4/mlx4.c | 11 + drivers/net/mlx4/mlx4.h | 2 + drivers/net/mlx4/mlx4_ethdev.c | 10 + drivers/net/mlx4/mlx4_prm.h | 151 +++++++ drivers/net/mlx4/mlx4_rxq.c | 156 +++++-- drivers/net/mlx4/mlx4_rxtx.c | 768 ++++++++++++++++++++++++--------- drivers/net/mlx4/mlx4_rxtx.h | 54 +-- drivers/net/mlx4/mlx4_txq.c | 63 +++ 9 files changed, 948 insertions(+), 273 deletions(-)create mode 100644
drivers/net/mlx4/mlx4_prm.h
Re: [PATCH v6 0/5] new mlx4 datapath bypassing ibverbs
Quoted 6 lines · gowrishankar muthukrishnan
Hi Adrien,
I am trying to compile mlx4 (and later to try mlx5) pmd in RHEL 7.4 (ppc64le) without Mellanox OFED, using current master (which has below patch series).As I do so, I hit with below compile error:
Quoted 9 lines
dpdk/drivers/net/mlx4/mlx4.c:53:31: fatal error:infiniband/mlx4dv.h: No such file or directory #include <infiniband/mlx4dv.h>
^
compilation terminated.
make[6]: *** [mlx4.o] Error 1I tried to find rpm for this directverbs include, but I could not. Could you advice if I have to install any additional rpm in RHEL 7.4 ? To note, I have rdma-core and libibverbs installed.
I see we need rdma-core v15 atleast for mlx5 pmd (where as the version available in RHEL 7.4 is v13).
https://patchwork.kernel.org/patch/9937201/
Similar dependency might be there for mlx4 as well. So I think it is not possible to compile it in RHEL 7.4 without dependent rpms upgraded.
Quoted 70 lines
Thanks,
GowrishankarQuoted 63 lines · Adrien Mazarguil
Hopefully the last iteration for this series.
v6 (Adrien):
- Updated features documentation (mlx4.ini) in the relevant patches.
- Rebased on the latest changes brought by RSS support v2 series.v5 (Ophir & Adrien):
- Merged Rx scatter/Tx gather code back into individual Rx/Tx commits for consistency due to a couple of issues with gather-less Tx.
- Rebased on top of the latest mlx4 control path changes (RSS support).v4 (Ophir):
- Split "net/mlx4: restore Rx scatter support" commit from "net/mlx4:
restore full Rx support bypassing Verbs" commitv3 (Adrien):
- Drop a few unrelated or unnecessary changes such as the removal ofMLX4_PMD_TX_MP_CACHE.
- Move device checksum support detection code to its previous location.
- Fix include guard inmlx4_prm.h.
- Reorder #includes alphabetically.
- ReplaceMLX4_TRANSPOSE()macro with documented inline function.
- Remove extra spaces and blank lines.
- Useuint8_t* instead of char * for buffers.
- Replacemlx4_get_cqe()macro with a documented inline function.
- Replace several unsigned int withuint32_t.
- Add consistency to field names (sge_n=>sges_n).
- Make mbuf size checks in RX queue setup function similar to mlx5.
- Update various comments.
- Fix indentation.
- Replace run-time endian conversion with static ones where possible.
- Reorder fields in struct rxq and struct txq for consistency, remove one level of unnecessary inner structures.
- Fix memory leak on Tx bounce buffer.
- Update commit logs.
- Fix remaining checkpatch warnings.v2 (Matan):
Rearange patches.
Semantics.
Enhancements.
Fix compilation issues.Moti Haimovsky (5):
net/mlx4: add Tx bypassing Verbs
net/mlx4: add Rx bypassing Verbs
net/mlx4: restore Tx checksum offloads
net/mlx4: restore Rx offloads
net/mlx4: add loopback Tx from VFdoc/guides/nics/features/mlx4.ini | 6 +
drivers/net/mlx4/mlx4.c | 11 +
drivers/net/mlx4/mlx4.h | 2 +
drivers/net/mlx4/mlx4_ethdev.c | 10 +
drivers/net/mlx4/mlx4_prm.h | 151 +++++++
drivers/net/mlx4/mlx4_rxq.c | 156 +++++--
drivers/net/mlx4/mlx4_rxtx.c | 768
++++++++++++++++++++++++---------
drivers/net/mlx4/mlx4_rxtx.h | 54 +--
drivers/net/mlx4/mlx4_txq.c | 63 +++9 files changed, 948 insertions(+), 273 deletions(-)create mode 100644
drivers/net/mlx4/mlx4_prm.h
Re: [PATCH v6 0/5] new mlx4 datapath bypassing ibverbs
Hi,
Quoted 20 lines · gowrishankar muthukrishnan
Quoted 14 lines · gowrishankar muthukrishnan
Hi Adrien,
I am trying to compile mlx4 (and later to try mlx5) pmd in RHEL 7.4 (ppc64le) without Mellanox OFED,
using current master (which has below patch series).As I do so, I hit with below compile error:
dpdk/drivers/net/mlx4/mlx4.c:53:31: fatal error:infiniband/mlx4dv.h:
No such file or directory
#include <infiniband/mlx4dv.h>
^
compilation terminated.
make[6]: *** [mlx4.o] Error 1Quoted 4 lines
I tried to find rpm for this directverbs include, but I could not. Could you advice if I have to install any additional rpm in RHEL 7.4 ? To note, I have rdma-core and libibverbs installed.
Quoted 8 lines
I see we need rdma-core v15 atleast for mlx5 pmd (where as the version available in RHEL 7.4 is v13).
https://patchwork.kernel.org/patch/9937201/
Similar dependency might be there for mlx4 as well. So I think it is not possible to compile it in RHEL 7.4 without dependent
rpms upgraded.
The procedure is described in the mlx5 documentation [1]. It should be the same for mlx4.
Quoted 55 lines
Quoted 55 lines
Thanks,
GowrishankarQuoted 50 lines · Adrien Mazarguil
Hopefully the last iteration for this series.
v6 (Adrien):
- Updated features documentation (mlx4.ini) in the relevant patches.
- Rebased on the latest changes brought by RSS support v2 series.v5 (Ophir & Adrien):
- Merged Rx scatter/Tx gather code back into individual Rx/Tx commits for consistency due to a couple of issues with gather-less Tx.
- Rebased on top of the latest mlx4 control path changes (RSS support).v4 (Ophir):
- Split "net/mlx4: restore Rx scatter support" commit from "net/mlx4:
restore full Rx support bypassing Verbs" commitv3 (Adrien):
- Drop a few unrelated or unnecessary changes such as the removal ofMLX4_PMD_TX_MP_CACHE.
- Move device checksum support detection code to its previous location.
- Fix include guard inmlx4_prm.h.
- Reorder #includes alphabetically.
- ReplaceMLX4_TRANSPOSE()macro with documented inline function.
- Remove extra spaces and blank lines.
- Useuint8_t* instead of char * for buffers.
- Replacemlx4_get_cqe()macro with a documented inline function.
- Replace several unsigned int withuint32_t.
- Add consistency to field names (sge_n=>sges_n).
- Make mbuf size checks in RX queue setup function similar to mlx5.
- Update various comments.
- Fix indentation.
- Replace run-time endian conversion with static ones where possible.
- Reorder fields in struct rxq and struct txq for consistency, remove one level of unnecessary inner structures.
- Fix memory leak on Tx bounce buffer.
- Update commit logs.
- Fix remaining checkpatch warnings.v2 (Matan):
Rearange patches.
Semantics.
Enhancements.
Fix compilation issues.Moti Haimovsky (5):
net/mlx4: add Tx bypassing Verbs
net/mlx4: add Rx bypassing Verbs
net/mlx4: restore Tx checksum offloads
net/mlx4: restore Rx offloads
net/mlx4: add loopback Tx from VF
Quoted 16 lines
Quoted 5 lines
Quoted 5 lines
doc/guides/nics/features/mlx4.ini | 6 +
drivers/net/mlx4/mlx4.c | 11 +
drivers/net/mlx4/mlx4.h | 2 +
drivers/net/mlx4/mlx4_ethdev.c | 10 +
drivers/net/mlx4/mlx4_prm.h | 151 +++++++Quoted 10 lines
Quoted 8 lines
drivers/net/mlx4/mlx4_rxq.c | 156 +++++--
drivers/net/mlx4/mlx4_rxtx.c | 768
++++++++++++++++++++++++---------
drivers/net/mlx4/mlx4_rxtx.h | 54 +--
drivers/net/mlx4/mlx4_txq.c | 63 +++9 files changed, 948 insertions(+), 273 deletions(-)create mode 100644
drivers/net/mlx4/mlx4_prm.h
Regards,
[1] http://dpdk.org/doc/guides/nics/mlx5.html#installation
Signature · 2 lines
Nélio Laranjeiro 6WIND
Re: [PATCH v6 0/5] new mlx4 datapath bypassing ibverbs
Quoted 35 lines · Nélio Laranjeiro
Hi,
Quoted 20 lines · gowrishankar muthukrishnan
Quoted 14 lines · gowrishankar muthukrishnan
Hi Adrien,
I am trying to compile mlx4 (and later to try mlx5) pmd in RHEL 7.4 (ppc64le) without Mellanox OFED,
using current master (which has below patch series).As I do so, I hit with below compile error:
dpdk/drivers/net/mlx4/mlx4.c:53:31: fatal error:infiniband/mlx4dv.h:
No such file or directory
#include <infiniband/mlx4dv.h>
^
compilation terminated.
make[6]: *** [mlx4.o] Error 1Quoted 4 lines
I tried to find rpm for this directverbs include, but I could not. Could you advice if I have to install any additional rpm in RHEL 7.4 ? To note, I have rdma-core and libibverbs installed.
Quoted 8 lines
I see we need rdma-core v15 atleast for mlx5 pmd (where as the version available in RHEL 7.4 is v13).
https://patchwork.kernel.org/patch/9937201/
Similar dependency might be there for mlx4 as well. So I think it is not possible to compile it in RHEL 7.4 without dependent
rpms upgraded.The procedure is described in the mlx5 documentation [1]. It should be the same for mlx4.
Regards,
<snip>
Quoted 2 lines
Yes, I confirm mlx4 documentation is not up to date yet regarding its dependencies, it will be modified soon.
Thanks for the report.
Signature · 2 lines
Adrien Mazarguil 6WIND
Re: [PATCH v6 0/5] new mlx4 datapath bypassing ibverbs
In reply to Adrien MazarguilQuoted 43 lines · Adrien Mazarguil
Hopefully the last iteration for this series.
v6 (Adrien):
- Updated features documentation (mlx4.ini) in the relevant patches.
- Rebased on the latest changes brought by RSS support v2 series.v5 (Ophir & Adrien):
- Merged Rx scatter/Tx gather code back into individual Rx/Tx commits for consistency due to a couple of issues with gather-less Tx.
- Rebased on top of the latest mlx4 control path changes (RSS support).v4 (Ophir):
- Split "net/mlx4: restore Rx scatter support" commit from "net/mlx4:
restore full Rx support bypassing Verbs" commitv3 (Adrien):
- Drop a few unrelated or unnecessary changes such as the removal ofMLX4_PMD_TX_MP_CACHE.
- Move device checksum support detection code to its previous location.
- Fix include guard inmlx4_prm.h.
- Reorder #includes alphabetically.
- ReplaceMLX4_TRANSPOSE()macro with documented inline function.
- Remove extra spaces and blank lines.
- Useuint8_t* instead of char * for buffers.
- Replacemlx4_get_cqe()macro with a documented inline function.
- Replace several unsigned int withuint32_t.
- Add consistency to field names (sge_n=>sges_n).
- Make mbuf size checks in RX queue setup function similar to mlx5.
- Update various comments.
- Fix indentation.
- Replace run-time endian conversion with static ones where possible.
- Reorder fields in struct rxq and struct txq for consistency, remove one level of unnecessary inner structures.
- Fix memory leak on Tx bounce buffer.
- Update commit logs.
- Fix remaining checkpatch warnings.v2 (Matan):
Rearange patches.
Semantics.
Enhancements.
Fix compilation issues.
Quoted 6 lines
Moti Haimovsky (5):
net/mlx4: add Tx bypassing Verbs
net/mlx4: add Rx bypassing Verbs
net/mlx4: restore Tx checksum offloads
net/mlx4: restore Rx offloads
net/mlx4: add loopback Tx from VF
Series applied to dpdk-next-net/master, thanks.
(It has been long that patch applied, but seems email forgotten)
v3 cover new mlx4 datapath bypassing ibverbs
In reply to Matan AzradChanges from v2:
* Split "net/mlx4: support multi-segments Rx" commit from "net/mlx4: get back Rx flow functionality" commit
* Semantics, code styling
* Fix check-git-log warnings
* Fix checkpatches warnings
Next (currently not included) changes:
* Replacing MLX4_TRANSPOSE() macro (Generic macro to convert MLX4 to IBV flags) with a look-up table as in mlx5 for example: mlx5_set_ptype_table() function - in order to improve performance.
This change is delicate and should be verified first with regression tests
* PMD documentation update when no longer working with MLNX_OFED
Documentation updtes require specific kernel, rdma_core and FW versions as well as installation procedures. These details should be supplied by regression team.
Moti Haimovsky (6):
net/mlx4: add simple Tx bypassing ibverbs
net/mlx4: get back Rx flow functionality
net/mlx4: support multi-segments Tx
net/mlx4: get back Tx checksum offloads
net/mlx4: get back Rx checksum offloads
net/mlx4: add loopback Tx from VF
Vasily Philipov (1):
net/mlx4: support multi-segments Rx
drivers/net/mlx4/mlx4.c | 11 + drivers/net/mlx4/mlx4.h | 13 +- drivers/net/mlx4/mlx4_ethdev.c | 10 + drivers/net/mlx4/mlx4_prm.h | 129 +++++++ drivers/net/mlx4/mlx4_rxq.c | 181 ++++++---- drivers/net/mlx4/mlx4_rxtx.c | 788 ++++++++++++++++++++++++++++++----------- drivers/net/mlx4/mlx4_rxtx.h | 61 ++-- drivers/net/mlx4/mlx4_txq.c | 104 +++++- drivers/net/mlx4/mlx4_utils.h | 20 ++ mk/rte.app.mk | 2 +- 10 files changed, 990 insertions(+), 329 deletions(-) create mode 100644 drivers/net/mlx4/mlx4_prm.h
Signature · 1 line
1.8.3.1
PATCH v3 1/7 net/mlx4: add simple Tx bypassing ibverbs
From: Moti Haimovsky <[email protected]>
Modify PMD to send single-buffer packets directly to the device bypassing the ibv Tx post and poll routines.
--- drivers/net/mlx4/mlx4_prm.h | 108 +++++++++++++ drivers/net/mlx4/mlx4_rxtx.c | 354 ++++++++++++++++++++++++++++++++----------- drivers/net/mlx4/mlx4_rxtx.h | 32 ++-- drivers/net/mlx4/mlx4_txq.c | 90 ++++++++--- mk/rte.app.mk | 2 +- 5 files changed, 464 insertions(+), 122 deletions(-) create mode 100644 drivers/net/mlx4/mlx4_prm.h
drivers/net/mlx4/mlx4_prm.h new file +108 -0
@@ -0,0 +1,108 @@ +/*- +* BSD LICENSE +* +* Copyright 2017 6WIND S.A. +* Copyright 2017 Mellanox +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of 6WIND S.A. nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef RTE_PMD_MLX4_PRM_H_ +#define RTE_PMD_MLX4_PRM_H_ + +#include <rte_byteorder.h> +#include <rte_branch_prediction.h> +#include <rte_atomic.h> + +/* Verbs headers do not support -pedantic. */ +#ifdef PEDANTIC +#pragma GCC diagnostic ignored "-Wpedantic" +#endif +#include <infiniband/verbs.h> +#include <infiniband/mlx4dv.h> +#ifdef PEDANTIC +#pragma GCC diagnostic error "-Wpedantic" +#endif + +/* ConnectX-3 Tx queue basic block. */ +#define MLX4_TXBB_SHIFT 6 +#define MLX4_TXBB_SIZE (1 << MLX4_TXBB_SHIFT) + +/* Typical TSO descriptor with 16 gather entries is 352 bytes. */ +#define MLX4_MAX_WQE_SIZE 512 +#define MLX4_MAX_WQE_TXBBS (MLX4_MAX_WQE_SIZE / MLX4_TXBB_SIZE) + +/* Send queue stamping/invalidating information. */ +#define MLX4_SQ_STAMP_STRIDE 64 +#define MLX4_SQ_STAMP_DWORDS (MLX4_SQ_STAMP_STRIDE / 4) +#define MLX4_SQ_STAMP_SHIFT 31 +#define MLX4_SQ_STAMP_VAL 0x7fffffff + +/* Work queue element (WQE) flags. */ +#define MLX4_BIT_WQE_OWN 0x80000000 + +#define MLX4_SIZE_TO_TXBBS (size) \ + (RTE_ALIGN((size), (MLX4_TXBB_SIZE)) >> (MLX4_TXBB_SHIFT)) + +/* Send queue information. */ +struct mlx4_sq { +char *buf;/**< SQ buffer. */ +char *eob;/**< End of SQ buffer */ +uint32_t head;/**< SQ head counter in units of TXBBS. */ +uint32_t tail;/**< SQ tail counter in units of TXBBS. */ +uint32_t txbb_cnt;/**< Num of WQEBB in the Q (should be ^2). */ +uint32_t txbb_cnt_mask;/**< txbbs_cnt mask (txbb_cnt is ^2). */ +uint32_t headroom_txbbs;/**< Num of txbbs that should be kept free. */ +uint32_t *db;/**< Pointer to the doorbell. */ +uint32_t doorbell_qpn;/**< qp number to write to the doorbell. */ +}; + +#define mlx4_get_send_wqe (sq, n) ((sq)->buf + ((n) * (MLX4_TXBB_SIZE))) + +/* Completion queue information. */ +struct mlx4_cq { +char *buf;/**< Pointer to the completion queue buffer. */ +uint32_t cqe_cnt;/**< Number of entries in the queue. */ +uint32_t cqe_64:1 ;/**< CQ entry size is 64 bytes. */ +uint32_t cons_index;/**< Last queue entry that was handled. */ +uint32_t *set_ci_db;/**< Pointer to the completion queue doorbell. */ +}; + +/* +* cqe = cq->buf + cons_index * cqe_size + cqe_offset +* Where cqe_size is 32 or 64 bytes and +* cqe_offset is 0 or 32 (depending on cqe_size). +*/ +#define mlx4_get_cqe (cq, n) (__extension__({ \ + typeof(cq) q = (cq); \ + (q)->buf + \ + (((n) & ((q)->cqe_cnt - 1)) << \ + (5 + (q)->cqe_64)) + \ + ((q)->cqe_64 << 5); \ + })) + +#endif /* RTE_PMD_MLX4_PRM_H_ */
drivers/net/mlx4/mlx4_rxtx.c +264 -90
446 lines not on this page · raw message
drivers/net/mlx4/mlx4_rxtx.h +18 -14
@@ -40,6 +40,7 @@#ifdef PEDANTIC #pragma GCC diagnostic ignored "-Wpedantic"#endif +#include <infiniband/mlx4dv.h> #include <infiniband/verbs.h> #ifdef PEDANTIC #pragma GCC diagnostic error "-Wpedantic"
@@ -50,6 +51,7 @@#include <rte_mempool.h> #include "mlx4.h" +#include "mlx4_prm.h" /** Rx queue counters. */ struct mlx4_rxq_stats {
@@ -85,8 +87,6 @@ struct rxq {/** Tx element. */ struct txq_elt { -struct ibv_send_wr wr;/* Work request. */ -struct ibv_sge sge;/* Scatter/gather element. */ struct rte_mbuf *buf;/**< Buffer. */ };
@@ -100,24 +100,28 @@ struct mlx4_txq_stats {/** Tx queue descriptor. */ struct txq { -struct priv *priv;/**< Back pointer to private data. */ -struct { -const struct rte_mempool *mp;/**< Cached memory pool. */ -struct ibv_mr *mr;/**< Memory region (for mp). */ -uint32_t lkey;/**< mr->lkey copy. */ - } mp2mr[MLX4_PMD_TX_MP_CACHE ];/**< MP to MR translation table. */ -struct ibv_cq *cq;/**< Completion queue. */ -struct ibv_qp *qp;/**< Queue pair. */ -uint32_t max_inline;/**< Max inline send size. */ -unsigned int elts_n;/**< (*elts)[] length. */ -struct txq_elt (*elts)[];/**< Tx elements. */ +struct mlx4_sq msq;/**< Info for directly manipulating the SQ. */ +struct mlx4_cq mcq;/**< Info for directly manipulating the CQ. */ unsigned int elts_head;/**< Current index in (*elts)[]. */ unsigned int elts_tail;/**< First element awaiting completion. */ unsigned int elts_comp;/**< Number of completion requests. */ unsigned int elts_comp_cd;/**< Countdown for next completion. */ unsigned int elts_comp_cd_init;/**< Initial value for countdown. */ +unsigned int elts_n;/**< (*elts)[] length. */ +struct txq_elt (*elts)[];/**< Tx elements. */ struct mlx4_txq_stats stats;/**< Tx queue counters. */ -unsigned int socket;/**< CPU socket ID for allocations. */ +uint32_t max_inline;/**< Max inline send size. */ +struct { +const struct rte_mempool *mp;/**< Cached memory pool. */ +struct ibv_mr *mr;/**< Memory region (for mp). */ +uint32_t lkey;/**< mr->lkey copy. */ + } mp2mr[MLX4_PMD_TX_MP_CACHE ];/**< MP to MR translation table. */ +struct { +struct priv *priv;/**< Back pointer to private data. */ +unsigned int socket;/**< CPU socket ID for allocations. */ +struct ibv_cq *cq;/**< Completion queue. */ +struct ibv_qp *qp;/**< Queue pair. */ + } ctrl; };/* mlx4_rxq.c */
drivers/net/mlx4/mlx4_txq.c +73 -17
170 lines not on this page · raw message
mk/rte.app.mk +1 -1
@@ -128,7 +128,7 @@ ifeq ($(CONFIG_RTE_LIBRTE_KNI),y) _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_KNI) += -lrte_pmd_kni endif _LDLIBS-$(CONFIG_RTE_LIBRTE_LIO_PMD) += -lrte_pmd_lio -_LDLIBS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += -lrte_pmd_mlx4 -libverbs +_LDLIBS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += -lrte_pmd_mlx4 -libverbs -lmlx4 _LDLIBS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += -lrte_pmd_mlx5 -libverbs _LDLIBS-$(CONFIG_RTE_LIBRTE_NFP_PMD) += -lrte_pmd_nfp _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += -lrte_pmd_null
Signature · 1 line
1.8.3.1
PATCH v3 2/7 net/mlx4: get back Rx flow functionality
In reply to Ophir MunkFrom: Moti Haimovsky <[email protected]>
This patch adds support for accessing the hardware directly when handling Rx packets eliminating the need to use verbs in the Rx datapath.
The number of scatters is limited to one.
--- drivers/net/mlx4/mlx4.h | 11 --- drivers/net/mlx4/mlx4_rxq.c | 149 ++++++++++++++++------------ drivers/net/mlx4/mlx4_rxtx.c | 225 ++++++++++++++++++++++++------------------ drivers/net/mlx4/mlx4_rxtx.h | 18 ++-- drivers/net/mlx4/mlx4_utils.h | 20 ++++ 5 files changed, 242 insertions(+), 181 deletions(-)
drivers/net/mlx4/mlx4.h +0 -11
@@ -57,17 +57,6 @@/* Maximum size for inline data. */ #define MLX4_PMD_MAX_INLINE 0 -/* -* Maximum number of cached Memory Pools (MPs) per TX queue. Each RTE MP -* from which buffers are to be transmitted will have to be mapped by this -* driver to their own Memory Region (MR). This is a slow operation. -* -* This value is always 1 for RX queues. -*/ -#ifndef MLX4_PMD_TX_MP_CACHE -#define MLX4_PMD_TX_MP_CACHE 8 -#endif -/* Interrupt alarm timeout value in microseconds. */ #define MLX4_INTR_ALARM_TIMEOUT 100000
drivers/net/mlx4/mlx4_rxq.c +87 -62
243 lines not on this page · raw message
drivers/net/mlx4/mlx4_rxtx.c +127 -98
248 lines not on this page · raw message
drivers/net/mlx4/mlx4_rxtx.h +8 -10
@@ -62,13 +62,6 @@ struct mlx4_rxq_stats {uint64_t rx_nombuf;/**< Total of Rx mbuf allocation failures. */ }; -/** Rx element. */ -struct rxq_elt { -struct ibv_recv_wr wr;/**< Work request. */ -struct ibv_sge sge;/**< Scatter/gather element. */ -struct rte_mbuf *buf;/**< Buffer. */ -}; -/** Rx queue descriptor. */ struct rxq {struct priv *priv;/**< Back pointer to private data. */
@@ -78,9 +71,14 @@ struct rxq {struct ibv_qp *qp;/**< Queue pair. */ struct ibv_comp_channel *channel;/**< Rx completion channel. */ unsigned int port_id;/**< Port ID for incoming packets. */ -unsigned int elts_n;/**< (*elts)[] length. */ -unsigned int elts_head;/**< Current index in (*elts)[]. */ -struct rxq_elt (*elts)[];/**< Rx elements. */ +unsigned int elts_n;/**< Log 2 of Mbufs. */ +struct rte_mbuf *(*elts)[];/**< Rx elements. */ +struct { +volatile struct mlx4_wqe_data_seg (*wqes)[]; +volatile uint32_t *rq_db; +uint16_t rq_ci; + } hw; +struct mlx4_cq mcq;/**< Info for directly manipulating the CQ. */ struct mlx4_rxq_stats stats;/**< Rx queue counters. */ unsigned int socket;/**< CPU socket ID for allocations. */ };
drivers/net/mlx4/mlx4_utils.h +20 -0
@@ -108,4 +108,24 @@int mlx4_fd_set_non_blocking (int fd); +/** +* Return nearest power of two above input value. +* +* @param v +* Input value. +* +* @return +* Nearest power of two above input value. +*/ +static inline unsigned int +log2above (unsigned int v) +{ +unsigned int l; +unsigned int r; + +for (l =0 , r =0 ; (v >>1 ); ++l, v >>=1 ) + r |= (v &1 ); +return l + r; +} +#endif /* MLX4_UTILS_H_ */
Signature · 1 line
1.8.3.1
PATCH v3 3/7 net/mlx4: support multi-segments Rx
In reply to Ophir MunkFrom: Vasily Philipov <[email protected]>
Getting hw directly on RX fast path without verbs call.
Now the number of scatters is calculated on the fly according to the maximum expected packet size.
---
This commit is a split from a previous commit
"net/mlx4: get back Rx flow functionality"
drivers/net/mlx4/mlx4_rxq.c | 29 ++++++++++++++++++++++------- drivers/net/mlx4/mlx4_rxtx.c | 10 +++++++--- drivers/net/mlx4/mlx4_rxtx.h | 1 + 3 files changed, 30 insertions(+), 10 deletions(-)
drivers/net/mlx4/mlx4_rxq.c +22 -7
@@ -78,6 +78,7 @@ mlx4_rxq_alloc_elts(struct rxq *rxq, unsigned int elts_n) {unsigned int i; +const unsigned int sge_n =1 << rxq->sge_n;struct rte_mbuf *(*elts)[elts_n] =rte_calloc_socket ("RXQ" ,1 ,sizeof (*elts),0 , rxq->socket);
@@ -105,6 +106,9 @@assert (rte_pktmbuf_data_len (buf) ==0 );assert (rte_pktmbuf_pkt_len (buf) ==0 );assert (!buf->next); +/* Only the first segment keeps headroom. */ +if (i % sge_n) + buf->data_off =0 ; buf->port = rxq->port_id; buf->data_len =rte_pktmbuf_tailroom (buf); buf->pkt_len =rte_pktmbuf_tailroom (buf);
@@ -119,8 +123,8 @@ }; (*rxq->elts)[i] = buf; } -DEBUG ("%p: allocated and configured %u single-segment WRs" , - (void *)rxq, elts_n); +DEBUG ("%p: allocated and configured %u segments (max %u packets)" , + (void *)rxq, elts_n, elts_n >> rxq->sge_n); rxq->elts_n =log2above (elts_n);return 0 ; error:
@@ -199,7 +203,8 @@* QP pointer or NULL in case of error and rte_errno is set. */ static struct ibv_qp * -mlx4_rxq_setup_qp (struct priv *priv,struct ibv_cq *cq,uint16_t desc) +mlx4_rxq_setup_qp (struct priv *priv,struct ibv_cq *cq, +uint16_t desc,unsigned int sge_n) {struct ibv_qp *qp;struct ibv_qp_init_attr attr = {
@@ -213,7 +218,7 @@ priv->device_attr.max_qp_wr : desc), /* Max number of scatter/gather elements in a WR. */ - .max_recv_sge = 1, + .max_recv_sge = sge_n, }, .qp_type = IBV_QPT_RAW_PACKET, };
@@ -267,8 +272,9 @@assert (mb_len >=RTE_PKTMBUF_HEADROOM );if (dev->data->dev_conf.rxmode.max_rx_pkt_len <= (mb_len -RTE_PKTMBUF_HEADROOM )) { - ; + tmpl.sge_n =0 ; }else if (dev->data->dev_conf.rxmode.enable_scatter) { +unsigned int sge_n;unsigned int rx_pkt_len = dev->data->dev_conf.rxmode.jumbo_frame ? dev->data->dev_conf.rxmode.max_rx_pkt_len :
@@ -278,6 +284,13 @@ rx_pkt_len =ETHER_MTU ;/* Only the first mbuf has a headroom */ rx_pkt_len = rx_pkt_len - mb_len +RTE_PKTMBUF_HEADROOM ; +/* +* Determine the number of SGEs needed for a full packet +* and round it to the next power of two. +*/ + sge_n = (rx_pkt_len / mb_len) + !!(rx_pkt_len % mb_len) +1 ; + tmpl.sge_n =log2above (sge_n); + desc >>= tmpl.sge_n; }else {WARN ("%p: the requested maximum Rx packet size (%u) is" " larger than a single mbuf (%u) and scattered"
@@ -286,6 +299,8 @@ dev->data->dev_conf.rxmode.max_rx_pkt_len, mb_len - RTE_PKTMBUF_HEADROOM); } +DEBUG ("%p: number of sges %u (%u WRs)" , + (void *)dev,1 << tmpl.sge_n, desc);/* Use the entire Rx mempool as the memory region. */ tmpl.mr =mlx4_mp2mr (priv->pd, mp);if (tmpl.mr ==NULL ) {
@@ -321,7 +336,7 @@ priv->device_attr.max_qp_wr);DEBUG ("priv->device_attr.max_sge is %d" , priv->device_attr.max_sge); - tmpl.qp =mlx4_rxq_setup_qp (priv, tmpl.cq, desc); + tmpl.qp =mlx4_rxq_setup_qp (priv, tmpl.cq, desc,1 << tmpl.sge_n);if (tmpl.qp ==NULL ) {ERROR ("%p: QP creation failure: %s" , (void *)dev,strerror (rte_errno));
@@ -373,7 +388,7 @@/* Save port ID. */ tmpl.port_id = dev->data->port_id;DEBUG ("%p: RTE port ID: %u" , (void *)rxq, tmpl.port_id); - ret =mlx4_rxq_alloc_elts (&tmpl, desc); + ret =mlx4_rxq_alloc_elts (&tmpl, desc << tmpl.sge_n);if (ret) {ERROR ("%p: RXQ allocation failed: %s" , (void *)dev,strerror (rte_errno));
drivers/net/mlx4/mlx4_rxtx.c +7 -3
@@ -577,10 +577,11 @@ {struct rxq *rxq = dpdk_rxq;const unsigned int wr_cnt = (1 << rxq->elts_n) -1 ; +const unsigned int sge_n = rxq->sge_n;struct rte_mbuf *pkt =NULL ;struct rte_mbuf *seg =NULL ;unsigned int i =0 ; -unsigned int rq_ci = (rxq->hw.rq_ci); +unsigned int rq_ci = (rxq->hw.rq_ci << sge_n);int len =0 ;while (pkts_n) {
@@ -661,12 +662,15 @@ --pkts_n; ++i; skip: +/* Align consumer index to the next stride. */ + rq_ci >>= sge_n; ++rq_ci; + rq_ci <<= sge_n; } -if (unlikely (i ==0 && rq_ci == rxq->hw.rq_ci)) +if (unlikely (i ==0 && (rq_ci >> sge_n) == rxq->hw.rq_ci))return 0 ;/* Update the consumer index. */ - rxq->hw.rq_ci = rq_ci; + rxq->hw.rq_ci = rq_ci >> sge_n;rte_wmb (); *rxq->hw.rq_db =rte_cpu_to_be_32 (rxq->hw.rq_ci); *rxq->mcq.set_ci_db =
drivers/net/mlx4/mlx4_rxtx.h +1 -0
@@ -79,6 +79,7 @@ struct rxq {uint16_t rq_ci; } hw;struct mlx4_cq mcq;/**< Info for directly manipulating the CQ. */ +unsigned int sge_n;/**< Log 2 of SGEs number. */ struct mlx4_rxq_stats stats;/**< Rx queue counters. */ unsigned int socket;/**< CPU socket ID for allocations. */ };
Signature · 1 line
1.8.3.1
PATCH v3 4/7 net/mlx4: support multi-segments Tx
In reply to Ophir MunkFrom: Moti Haimovsky <[email protected]>
This patch adds support for transmitting packets spanning over multiple buffers.
In this patch we also take into consideration the amount of entries a packet occupies in the TxQ when setting the report-completion flag of the chip.
--- drivers/net/mlx4/mlx4_rxtx.c | 208 ++++++++++++++++++++++++------------------- drivers/net/mlx4/mlx4_rxtx.h | 6 +- drivers/net/mlx4/mlx4_txq.c | 12 ++- 3 files changed, 129 insertions(+), 97 deletions(-)
drivers/net/mlx4/mlx4_rxtx.c +116 -92
@@ -63,6 +63,16 @@#include "mlx4_rxtx.h" #include "mlx4_utils.h" +/* +* Pointer-value pair structure +* used in tx_post_send for saving the first DWORD (32 byte) +* of a TXBB0 +*/ +struct pv { +struct mlx4_wqe_data_seg *dseg; +uint32_t val; +}; +/** * Stamp a WQE so it won't be reused by the HW. * Routine is used when freeing WQE used by the chip or when failing
@@ -297,34 +307,38 @@* * @param txq * The Tx queue to post to. -* @param wr -* The work request to handle. -* @param bad_wr -* The wr in case that posting had failed. +* @param pkt +* The packet to transmit. * * @return * 0 - success, negative errno value otherwise and rte_errno is set. */ static inline int mlx4_post_send (struct txq *txq, -struct rte_mbuf *pkt, -uint32_t send_flags) +struct rte_mbuf *pkt) {struct mlx4_wqe_ctrl_seg *ctrl;struct mlx4_wqe_data_seg *dseg;struct mlx4_sq *sq = &txq->msq; +struct rte_mbuf *buf;uint32_t head_idx = sq->head & sq->txbb_cnt_mask;uint32_t lkey;uintptr_t addr; +uint32_t srcrb_flags; +uint32_t owner_opcode =MLX4_OPCODE_SEND ; +uint32_t byte_count;int wqe_real_size;int nr_txbbs;int rc; +struct pv *pv = (struct pv *)txq->bounce_buf; +int pv_counter =0 ;/* Calculate the needed work queue entry size for this packet. */ wqe_real_size =sizeof (struct mlx4_wqe_ctrl_seg ) + pkt->nb_segs *sizeof (struct mlx4_wqe_data_seg ); nr_txbbs =MLX4_SIZE_TO_TXBBS (wqe_real_size); -/* Check that there is room for this WQE in the send queue and +/* +* Check that there is room for this WQE in the send queue and * that the WQE size is legal. */ if (likely(((sq->head - sq->tail) + nr_txbbs +
@@ -333,76 +347,108 @@ rc =ENOSPC ; goto err; } -/* Get the control and single-data entries of the WQE */ +/* Get the control and data entries of the WQE. */ ctrl = (struct mlx4_wqe_ctrl_seg *)mlx4_get_send_wqe (sq, head_idx); dseg = (struct mlx4_wqe_data_seg *)(((char *)ctrl) +sizeof (struct mlx4_wqe_ctrl_seg )); -/* -* Fill the data segment with buffer information. -*/ - addr =rte_pktmbuf_mtod (pkt, uintptr_t); -rte_prefetch0 ((volatile void *)addr); - dseg->addr =rte_cpu_to_be_64 (addr); -/* Memory region key for this memory pool. */ - lkey =mlx4_txq_mp2mr (txq,mlx4_txq_mb2mp (pkt)); -if (unlikely (lkey == (uint32_t )-1 )) { -/* MR does not exist. */ -DEBUG ("%p: unable to get MP <-> MR" -" association" , (void *)txq); -/* -* Restamp entry in case of failure. -* Make sure that size is written correctly. -* Note that we give ownership to the SW, not the HW. +/* Fill the data segments with buffer information. */ +for (buf = pkt; buf !=NULL ; buf = buf->next, dseg++) { + addr =rte_pktmbuf_mtod (buf, uintptr_t); +rte_prefetch0 ((volatile void *)addr); +/* Handle WQE wraparound. */ +if (unlikely (dseg >= (struct mlx4_wqe_data_seg *)sq->eob)) + dseg = (struct mlx4_wqe_data_seg *)sq->buf; + dseg->addr =rte_cpu_to_be_64 (addr); +/* Memory region key for this memory pool. */ + lkey =mlx4_txq_mp2mr (txq,mlx4_txq_mb2mp (buf)); +if (unlikely (lkey == (uint32_t )-1 )) { +/* MR does not exist. */ +DEBUG ("%p: unable to get MP <-> MR" +" association" , (void *)txq); +/* +* Restamp entry in case of failure. +* Make sure that size is written correctly +* Note that we give ownership to the SW, not the HW. +*/ + ctrl->fence_size = (wqe_real_size >>4 ) &0x3f ; +mlx4_txq_stamp_freed_wqe (sq, head_idx, + (sq->head & sq->txbb_cnt) ?0 :1 ); + rc =EFAULT ; + goto err; + } + dseg->lkey =rte_cpu_to_be_32 (lkey); +if (likely (buf->data_len)) + byte_count =rte_cpu_to_be_32 (buf->data_len); +else +/* +* Zero length segment is treated as inline segment +* with zero data. +*/ + byte_count =RTE_BE32 (0x80000000 ); +/* If the data segment is not at the beginning of a +* Tx basic block(TXBB) then write the byte count, +* else postpone the writing to just before updating the +* control segment. */ - ctrl->fence_size = (wqe_real_size >>4 ) &0x3f ; -mlx4_txq_stamp_freed_wqe (sq, head_idx, - (sq->head & sq->txbb_cnt) ?0 :1 ); - rc =EFAULT ; - goto err; +if ((uintptr_t )dseg & (uintptr_t )(MLX4_TXBB_SIZE -1 )) { +/* +* Need a barrier here before writing the byte_count +* fields to make sure that all the data is visible +* before the byte_count field is set. +* Otherwise, if the segment begins a new cacheline, +* the HCA prefetcher could grab the 64-byte chunk and +* get a valid (!= * 0xffffffff) byte count but stale +* data, and end up sending the wrong data. +*/ +rte_io_wmb (); + dseg->byte_count = byte_count; + }else { +/* +* This data segment starts at the beginning of a new +* TXBB, so we need to postpone its byte_count writing +* for later. +*/ + pv[pv_counter].dseg = dseg; + pv[pv_counter++].val = byte_count; + } } - dseg->lkey =rte_cpu_to_be_32 (lkey); -/* -* Need a barrier here before writing the byte_count field to -* make sure that all the data is visible before the -* byte_count field is set. Otherwise, if the segment begins -* a new cacheline, the HCA prefetcher could grab the 64-byte -* chunk and get a valid (!= * 0xffffffff) byte count but -* stale data, and end up sending the wrong data. -*/ -rte_io_wmb (); -if (likely (pkt->data_len)) - dseg->byte_count =rte_cpu_to_be_32 (pkt->data_len); -else -/* -* Zero length segment is treated as inline segment -* with zero data. -*/ - dseg->byte_count =RTE_BE32 (0x80000000 ); -/* -* Fill the control parameters for this packet. -* For raw Ethernet, the SOLICIT flag is used to indicate that no icrc -* should be calculated -*/ - ctrl->srcrb_flags = -rte_cpu_to_be_32 (MLX4_WQE_CTRL_SOLICIT | - (send_flags &MLX4_WQE_CTRL_CQ_UPDATE )); +/* Write the first DWORD of each TXBB save earlier. */ +if (pv_counter) { +/* Need a barrier here before writing the byte_count. */ +rte_io_wmb (); +for (--pv_counter; pv_counter >=0 ; pv_counter--) + pv[pv_counter].dseg->byte_count = pv[pv_counter].val; + } +/* Fill the control parameters for this packet. */ ctrl->fence_size = (wqe_real_size >>4 ) &0x3f ;/* * The caller should prepare "imm" in advance in order to support * VF to VF communication (when the device is a virtual-function * device (VF)). -*/ +*/ ctrl->imm =0 ;/* +* For raw Ethernet, the SOLICIT flag is used to indicate that no icrc +* should be calculated. +*/ + txq->elts_comp_cd -= nr_txbbs; +if (unlikely (txq->elts_comp_cd <=0 )) { + txq->elts_comp_cd = txq->elts_comp_cd_init; + srcrb_flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT | +MLX4_WQE_CTRL_CQ_UPDATE ); + }else { + srcrb_flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT ); + } + ctrl->srcrb_flags = srcrb_flags; +/* * Make sure descriptor is fully written before * setting ownership bit (because HW can start * executing as soon as we do). */ -rte_wmb (); - ctrl->owner_opcode = -rte_cpu_to_be_32 (MLX4_OPCODE_SEND | - ((sq->head & sq->txbb_cnt) ? -MLX4_BIT_WQE_OWN :0 )); +rte_wmb (); + ctrl->owner_opcode =rte_cpu_to_be_32 (owner_opcode | + ((sq->head & sq->txbb_cnt) ? +MLX4_BIT_WQE_OWN :0 )); sq->head += nr_txbbs;return 0 ; err:
@@ -429,14 +475,13 @@struct txq *txq = (struct txq *)dpdk_txq;unsigned int elts_head = txq->elts_head;const unsigned int elts_n = txq->elts_n; -unsigned int elts_comp_cd = txq->elts_comp_cd;unsigned int elts_comp =0 ;unsigned int bytes_sent =0 ;unsigned int i;unsigned int max;int err; -assert (elts_comp_cd !=0 ); +assert (txq->elts_comp_cd !=0 );mlx4_txq_complete (txq); max = (elts_n - (elts_head - txq->elts_tail));if (max > elts_n)
@@ -455,8 +500,6 @@ (((elts_head +1 ) == elts_n) ?0 : elts_head +1 );struct txq_elt *elt_next = &(*txq->elts)[elts_head_next];struct txq_elt *elt = &(*txq->elts)[elts_head]; -unsigned int segs = buf->nb_segs; -uint32_t send_flags =0 ;/* Clean up old buffer. */ if (likely (elt->buf !=NULL )) {
@@ -474,34 +517,16 @@ tmp = next; }while (tmp !=NULL ); } -/* Request Tx completion. */ -if (unlikely (--elts_comp_cd ==0 )) { - elts_comp_cd = txq->elts_comp_cd_init; - ++elts_comp; - send_flags |=MLX4_WQE_CTRL_CQ_UPDATE ; - } -if (likely (segs ==1 )) { -/* Update element. */ - elt->buf = buf; -RTE_MBUF_PREFETCH_TO_FREE (elt_next->buf); -/* post the pkt for sending */ - err =mlx4_post_send (txq, buf, send_flags); -if (unlikely (err)) { -if (unlikely (send_flags & -MLX4_WQE_CTRL_CQ_UPDATE )) { - elts_comp_cd =1 ; - --elts_comp; - } - elt->buf =NULL ; - goto stop; - } - elt->buf = buf; - bytes_sent += buf->pkt_len; - }else { - err = -EINVAL ; - rte_errno = -err; +RTE_MBUF_PREFETCH_TO_FREE (elt_next->buf); +/* post the packet for sending. */ + err =mlx4_post_send (txq, buf); +if (unlikely (err)) { + elt->buf =NULL ; goto stop; } + elt->buf = buf; + bytes_sent += buf->pkt_len; + ++elts_comp; elts_head = elts_head_next; } stop:
@@ -517,7 +542,6 @@rte_write32 (txq->msq.doorbell_qpn, txq->msq.db); txq->elts_head = elts_head; txq->elts_comp += elts_comp; - txq->elts_comp_cd = elts_comp_cd;return i; }
drivers/net/mlx4/mlx4_rxtx.h +4 -2
@@ -103,13 +103,15 @@ struct txq {struct mlx4_cq mcq;/**< Info for directly manipulating the CQ. */ unsigned int elts_head;/**< Current index in (*elts)[]. */ unsigned int elts_tail;/**< First element awaiting completion. */ -unsigned int elts_comp;/**< Number of completion requests. */ -unsigned int elts_comp_cd;/**< Countdown for next completion. */ +unsigned int elts_comp;/**< Number of pkts waiting for completion. */ +int elts_comp_cd;/**< Countdown for next completion. */ unsigned int elts_comp_cd_init;/**< Initial value for countdown. */ unsigned int elts_n;/**< (*elts)[] length. */ struct txq_elt (*elts)[];/**< Tx elements. */ struct mlx4_txq_stats stats;/**< Tx queue counters. */ uint32_t max_inline;/**< Max inline send size. */ +char *bounce_buf; +/**< memory used for storing the first DWORD of data TXBBs. */ struct {const struct rte_mempool *mp;/**< Cached memory pool. */ struct ibv_mr *mr;/**< Memory region (for mp). */
drivers/net/mlx4/mlx4_txq.c +9 -3
@@ -83,8 +83,14 @@rte_calloc_socket ("TXQ" ,1 ,sizeof (*elts),0 , txq->ctrl.socket);int ret =0 ; -if (elts ==NULL ) { -ERROR ("%p: can't allocate packets array" , (void *)txq); +/* Allocate Bounce-buf memory */ + txq->bounce_buf = (char *)rte_zmalloc_socket ("TXQ" , +MLX4_MAX_WQE_SIZE , +RTE_CACHE_LINE_MIN_SIZE , + txq->ctrl.socket); + +if (elts ==NULL || txq->bounce_buf ==NULL ) { +ERROR ("%p: can't allocate TXQ memory" , (void *)txq); ret =ENOMEM ; goto error; }
@@ -110,6 +116,7 @@assert (ret ==0 );return 0 ; error: +rte_free (txq->bounce_buf);rte_free (elts);DEBUG ("%p: failed, freed everything" , (void *)txq);assert (ret >0 );
@@ -303,7 +310,6 @@ struct txq_mp2mr_mbuf_check_data {struct mlx4dv_obj mlxdv;struct mlx4dv_qp dv_qp;struct mlx4dv_cq dv_cq; -struct txq tmpl = { .ctrl = { .priv = priv,
Signature · 1 line
1.8.3.1
PATCH v3 5/7 net/mlx4: get back Tx checksum offloads
In reply to Ophir MunkFrom: Moti Haimovsky <[email protected]>
This patch adds hardware offloading support for IPV4, UDP and TCP checksum calculation.
This commit also includes support for offloading IPV4, UDP and TCP tunnel checksum calculation to the hardware.
--- drivers/net/mlx4/mlx4.c | 9 +++++++++ drivers/net/mlx4/mlx4.h | 2 ++ drivers/net/mlx4/mlx4_ethdev.c | 6 ++++++ drivers/net/mlx4/mlx4_prm.h | 2 ++ drivers/net/mlx4/mlx4_rxtx.c | 25 +++++++++++++++++++++---- drivers/net/mlx4/mlx4_rxtx.h | 2 ++ drivers/net/mlx4/mlx4_txq.c | 2 ++ 7 files changed, 44 insertions(+), 4 deletions(-)
drivers/net/mlx4/mlx4.c +9 -0
@@ -397,6 +397,7 @@ struct mlx4_conf { .ports.present = 0, };unsigned int vf; +unsigned int tunnel_en;int i; (void )pci_drv;
@@ -456,6 +457,9 @@ struct mlx4_conf { rte_errno =ENODEV ; goto error; } +/* Only cx3-pro supports L3 tunneling */ + tunnel_en = (device_attr.vendor_part_id == +PCI_DEVICE_ID_MELLANOX_CONNECTX3PRO );INFO ("%u port(s) detected" , device_attr.phys_port_cnt); conf.ports.present |= (UINT64_C (1 ) << device_attr.phys_port_cnt) -1 ;if (mlx4_args (pci_dev->device.devargs, &conf)) {
@@ -529,6 +533,11 @@ struct mlx4_conf { priv->pd = pd; priv->mtu =ETHER_MTU ; priv->vf = vf; + priv->hw_csum = + !!(device_attr.device_cap_flags &IBV_DEVICE_RAW_IP_CSUM ); + priv->hw_csum_l2tun = tunnel_en; +DEBUG ("L2 tunnel checksum offloads are %ssupported" , + (priv->hw_csum_l2tun ?"" :"not " ));/* Configure the first MAC address by default. */ if (mlx4_get_mac (priv, &mac.addr_bytes)) { ERROR("cannot get MAC address, is mlx4_en loaded?"
drivers/net/mlx4/mlx4.h +2 -0
@@ -93,6 +93,8 @@ struct priv { unsigned int vf:1; /* This is a VF device. */ unsigned int intr_alarm:1; /* An interrupt alarm is scheduled. */ unsigned int isolated:1; /* Toggle isolated mode. */ + unsigned int hw_csum:1; /* Checksum offload is supported. */ + unsigned int hw_csum_l2tun:1; /* Checksum support for L2 tunnels. */struct rte_intr_handle intr_handle;/* Port interrupt handle. */ struct rte_flow_drop *flow_drop_queue;/* Flow drop queue. */ LIST_HEAD(mlx4_flows, rte_flow) flows;
drivers/net/mlx4/mlx4_ethdev.c +6 -0
@@ -553,6 +553,12 @@ info->max_mac_addrs =1 ; info->rx_offload_capa =0 ; info->tx_offload_capa =0 ; +if (priv->hw_csum) + info->tx_offload_capa |= (DEV_TX_OFFLOAD_IPV4_CKSUM | +DEV_TX_OFFLOAD_UDP_CKSUM | +DEV_TX_OFFLOAD_TCP_CKSUM ); +if (priv->hw_csum_l2tun) + info->tx_offload_capa |=DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM ;if (mlx4_get_ifname (priv, &ifname) ==0 ) info->if_index =if_nametoindex (ifname); info->speed_capa =
drivers/net/mlx4/mlx4_prm.h +2 -0
@@ -64,6 +64,8 @@/* Work queue element (WQE) flags. */ #define MLX4_BIT_WQE_OWN 0x80000000 +#define MLX4_WQE_CTRL_IIP_HDR_CSUM (1 << 28) +#define MLX4_WQE_CTRL_IL4_HDR_CSUM (1 << 27)#define MLX4_SIZE_TO_TXBBS (size) \ (RTE_ALIGN((size), (MLX4_TXBB_SIZE)) >> (MLX4_TXBB_SHIFT))
drivers/net/mlx4/mlx4_rxtx.c +21 -4
@@ -434,12 +434,29 @@ struct pv { txq->elts_comp_cd -= nr_txbbs;if (unlikely (txq->elts_comp_cd <=0 )) { txq->elts_comp_cd = txq->elts_comp_cd_init; - srcrb_flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT | -MLX4_WQE_CTRL_CQ_UPDATE ); + srcrb_flags =MLX4_WQE_CTRL_SOLICIT |MLX4_WQE_CTRL_CQ_UPDATE ; }else { - srcrb_flags =RTE_BE32 (MLX4_WQE_CTRL_SOLICIT ); + srcrb_flags =MLX4_WQE_CTRL_SOLICIT ; } - ctrl->srcrb_flags = srcrb_flags; +/* Enable HW checksum offload if requested */ +if (txq->csum && + (pkt->ol_flags & + (PKT_TX_IP_CKSUM |PKT_TX_TCP_CKSUM |PKT_TX_UDP_CKSUM ))) { +const uint64_t is_tunneled = pkt->ol_flags & + (PKT_TX_TUNNEL_GRE | +PKT_TX_TUNNEL_VXLAN ); + +if (is_tunneled && txq->csum_l2tun) { + owner_opcode |=MLX4_WQE_CTRL_IIP_HDR_CSUM | +MLX4_WQE_CTRL_IL4_HDR_CSUM ; +if (pkt->ol_flags &PKT_TX_OUTER_IP_CKSUM ) + srcrb_flags |=MLX4_WQE_CTRL_IP_HDR_CSUM ; + }else { + srcrb_flags |=MLX4_WQE_CTRL_IP_HDR_CSUM | +MLX4_WQE_CTRL_TCP_UDP_CSUM ; + } + } + ctrl->srcrb_flags =rte_cpu_to_be_32 (srcrb_flags);/* * Make sure descriptor is fully written before * setting ownership bit (because HW can start
drivers/net/mlx4/mlx4_rxtx.h +2 -0
@@ -110,6 +110,8 @@ struct txq {struct txq_elt (*elts)[];/**< Tx elements. */ struct mlx4_txq_stats stats;/**< Tx queue counters. */ uint32_t max_inline;/**< Max inline send size. */ + uint32_t csum:1; /**< Checksum is supported and enabled */ + uint32_t csum_l2tun:1; /**< L2 tun Checksum is supported and enabled */char *bounce_buf;/**< memory used for storing the first DWORD of data TXBBs. */ struct {
drivers/net/mlx4/mlx4_txq.c +2 -0
@@ -340,6 +340,8 @@ struct txq_mp2mr_mbuf_check_data { (void *)dev, strerror(rte_errno)); goto error; } + tmpl.csum = priv->hw_csum; + tmpl.csum_l2tun = priv->hw_csum_l2tun;DEBUG ("priv->device_attr.max_qp_wr is %d" , priv->device_attr.max_qp_wr); DEBUG("priv->device_attr.max_sge is %d",
Signature · 1 line
1.8.3.1
PATCH v3 6/7 net/mlx4: get back Rx checksum offloads
In reply to Ophir MunkFrom: Moti Haimovsky <[email protected]>
This patch adds hardware offloading support for IPV4, UDP and TCP checksum verification.
This commit also includes support for offloading IPV4, UDP and TCP tunnel checksum verification to the hardware.
--- drivers/net/mlx4/mlx4.c | 2 + drivers/net/mlx4/mlx4_ethdev.c | 8 ++- drivers/net/mlx4/mlx4_prm.h | 19 +++++++ drivers/net/mlx4/mlx4_rxq.c | 5 ++ drivers/net/mlx4/mlx4_rxtx.c | 120 ++++++++++++++++++++++++++++++++++++++++- drivers/net/mlx4/mlx4_rxtx.h | 2 + 6 files changed, 152 insertions(+), 4 deletions(-)
drivers/net/mlx4/mlx4.c +2 -0
@@ -535,6 +535,8 @@ struct mlx4_conf { priv->vf = vf; priv->hw_csum = !!(device_attr.device_cap_flags &IBV_DEVICE_RAW_IP_CSUM ); +DEBUG ("checksum offloading is %ssupported" , + (priv->hw_csum ?"" :"not " )); priv->hw_csum_l2tun = tunnel_en;DEBUG ("L2 tunnel checksum offloads are %ssupported" , (priv->hw_csum_l2tun ?"" :"not " ));
drivers/net/mlx4/mlx4_ethdev.c +6 -2
@@ -553,10 +553,14 @@ info->max_mac_addrs =1 ; info->rx_offload_capa =0 ; info->tx_offload_capa =0 ; -if (priv->hw_csum) +if (priv->hw_csum) { info->tx_offload_capa |= (DEV_TX_OFFLOAD_IPV4_CKSUM | -DEV_TX_OFFLOAD_UDP_CKSUM | +DEV_TX_OFFLOAD_UDP_CKSUM |DEV_TX_OFFLOAD_TCP_CKSUM ); + info->rx_offload_capa |= (DEV_RX_OFFLOAD_IPV4_CKSUM | +DEV_RX_OFFLOAD_UDP_CKSUM | +DEV_RX_OFFLOAD_TCP_CKSUM ); + }if (priv->hw_csum_l2tun) info->tx_offload_capa |=DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM ;if (mlx4_get_ifname (priv, &ifname) ==0 )
drivers/net/mlx4/mlx4_prm.h +19 -0
@@ -70,6 +70,25 @@#define MLX4_SIZE_TO_TXBBS (size) \ (RTE_ALIGN((size), (MLX4_TXBB_SIZE)) >> (MLX4_TXBB_SHIFT)) +/* Generic macro to convert MLX4 to IBV flags. */ +#define MLX4_TRANSPOSE (val, from, to) \ + (__extension__({ \ + typeof(val) _val = (val); \ + typeof(from) _from = (from); \ + typeof(to) _to = (to); \ + (((_from) >= (_to)) ? \ + (((_val) & (_from)) / ((_from) / (_to))) : \ + (((_val) & (_from)) * ((_to) / (_from)))); \ + })) + +/* CQE checksum flags */ +enum { +MLX4_CQE_L2_TUNNEL_IPV4 = (int )(1U <<25 ), +MLX4_CQE_L2_TUNNEL_L4_CSUM = (int )(1U <<26 ), +MLX4_CQE_L2_TUNNEL = (int )(1U <<27 ), +MLX4_CQE_L2_TUNNEL_IPOK = (int )(1U <<31 ), +}; +/* Send queue information. */ struct mlx4_sq {char *buf;/**< SQ buffer. */
drivers/net/mlx4/mlx4_rxq.c +5 -0
@@ -267,6 +267,11 @@int ret; (void )conf;/* Thresholds configuration (ignored). */ +/* Toggle Rx checksum offload if hardware supports it. */ +if (priv->hw_csum) + tmpl.csum = !!dev->data->dev_conf.rxmode.hw_ip_checksum; +if (priv->hw_csum_l2tun) + tmpl.csum_l2tun = !!dev->data->dev_conf.rxmode.hw_ip_checksum; mb_len =rte_pktmbuf_data_room_size (mp);/* Enable scattered packets support for this queue if necessary. */ assert (mb_len >=RTE_PKTMBUF_HEADROOM );
drivers/net/mlx4/mlx4_rxtx.c +118 -2
144 lines not on this page · raw message
drivers/net/mlx4/mlx4_rxtx.h +2 -0
@@ -80,6 +80,8 @@ struct rxq { } hw;struct mlx4_cq mcq;/**< Info for directly manipulating the CQ. */ unsigned int sge_n;/**< Log 2 of SGEs number. */ + unsigned int csum:1; /**< Enable checksum offloading. */ + unsigned int csum_l2tun:1; /**< Enable checksum for L2 tunnels. */struct mlx4_rxq_stats stats;/**< Rx queue counters. */ unsigned int socket;/**< CPU socket ID for allocations. */ };
Signature · 1 line
1.8.3.1
PATCH v3 7/7 net/mlx4: add loopback Tx from VF
In reply to Ophir MunkFrom: Moti Haimovsky <[email protected]>
This patch adds loopback functionality used when the chip is a VF in order to enable packet transmission between VFs and between VFs and PF.
--- drivers/net/mlx4/mlx4_rxtx.c | 38 ++++++++++++++++++++++++++------------ drivers/net/mlx4/mlx4_rxtx.h | 2 ++ drivers/net/mlx4/mlx4_txq.c | 2 ++ 3 files changed, 30 insertions(+), 12 deletions(-)
drivers/net/mlx4/mlx4_rxtx.c +26 -12
@@ -321,10 +321,13 @@ struct pv {struct mlx4_wqe_data_seg *dseg;struct mlx4_sq *sq = &txq->msq;struct rte_mbuf *buf; +union { +uint32_t flags; +uint16_t flags16[2 ]; + } srcrb;uint32_t head_idx = sq->head & sq->txbb_cnt_mask;uint32_t lkey;uintptr_t addr; -uint32_t srcrb_flags;uint32_t owner_opcode =MLX4_OPCODE_SEND ;uint32_t byte_count;int wqe_real_size;
@@ -422,21 +425,15 @@ struct pv {/* Fill the control parameters for this packet. */ ctrl->fence_size = (wqe_real_size >>4 ) &0x3f ;/* -* The caller should prepare "imm" in advance in order to support -* VF to VF communication (when the device is a virtual-function -* device (VF)). -*/ - ctrl->imm =0 ; -/* * For raw Ethernet, the SOLICIT flag is used to indicate that no icrc * should be calculated. */ txq->elts_comp_cd -= nr_txbbs;if (unlikely (txq->elts_comp_cd <=0 )) { txq->elts_comp_cd = txq->elts_comp_cd_init; - srcrb_flags =MLX4_WQE_CTRL_SOLICIT |MLX4_WQE_CTRL_CQ_UPDATE ; + srcrb.flags =MLX4_WQE_CTRL_SOLICIT |MLX4_WQE_CTRL_CQ_UPDATE ; }else { - srcrb_flags =MLX4_WQE_CTRL_SOLICIT ; + srcrb.flags =MLX4_WQE_CTRL_SOLICIT ; }/* Enable HW checksum offload if requested */ if (txq->csum &&
@@ -450,13 +447,30 @@ struct pv { owner_opcode |=MLX4_WQE_CTRL_IIP_HDR_CSUM |MLX4_WQE_CTRL_IL4_HDR_CSUM ;if (pkt->ol_flags &PKT_TX_OUTER_IP_CKSUM ) - srcrb_flags |=MLX4_WQE_CTRL_IP_HDR_CSUM ; + srcrb.flags |=MLX4_WQE_CTRL_IP_HDR_CSUM ; }else { - srcrb_flags |=MLX4_WQE_CTRL_IP_HDR_CSUM | + srcrb.flags |=MLX4_WQE_CTRL_IP_HDR_CSUM |MLX4_WQE_CTRL_TCP_UDP_CSUM ; } } - ctrl->srcrb_flags =rte_cpu_to_be_32 (srcrb_flags); +/* +* convert flags to BE before adding the mac address (if at all) +* to it +*/ + srcrb.flags =rte_cpu_to_be_32 (srcrb.flags); +if (txq->lb) { +/* +* Copy destination mac address to the wqe, +* this allows loopback in eSwitch, so that VFs and PF +* can communicate with each other. +*/ + srcrb.flags16[0] = *(rte_pktmbuf_mtod(pkt, uint16_t *)); + ctrl->imm = *(rte_pktmbuf_mtod_offset (pkt ,uint32_t *, + sizeof(uint16_t))); + }else { + ctrl->imm =0 ; + } + ctrl->srcrb_flags = srcrb.flags;/* * Make sure descriptor is fully written before * setting ownership bit (because HW can start
drivers/net/mlx4/mlx4_rxtx.h +2 -0
@@ -114,6 +114,8 @@ struct txq {uint32_t max_inline;/**< Max inline send size. */ uint32_t csum:1; /**< Checksum is supported and enabled */ uint32_t csum_l2tun:1; /**< L2 tun Checksum is supported and enabled */ + uint32_t lb:1; +/**< Whether pkts should be looped-back by eswitch or not */ char *bounce_buf;/**< memory used for storing the first DWORD of data TXBBs. */ struct {
drivers/net/mlx4/mlx4_txq.c +2 -0
@@ -415,6 +415,8 @@ struct txq_mp2mr_mbuf_check_data { (void *)dev, strerror(rte_errno)); goto error; } +/* If a VF device - need to loopback xmitted packets */ + tmpl.lb = !!(priv->vf);/* Clean up txq in case we're reinitializing it. */ DEBUG ("%p: cleaning-up old txq just in case" , (void *)txq);mlx4_txq_cleanup (txq);
Signature · 1 line
1.8.3.1
Re: [PATCH v3 0/7] new mlx4 datapath bypassing ibverbs
In reply to Ophir MunkQuoted 23 lines · Ophir Munk
Changes from v2:
* Split "net/mlx4: support multi-segments Rx" commit from "net/mlx4: get back Rx flow functionality" commit
* Semantics, code styling
* Fix check-git-log warnings
* Fix checkpatches warningsNext (currently not included) changes:
* ReplacingMLX4_TRANSPOSE()macro (Generic macro to convert MLX4 to IBV flags) with a look-up table as in mlx5 for example:mlx5_set_ptype_table()function - in order to improve performance.
This change is delicate and should be verified first with regression tests* PMD documentation update when no longer working with
MLNX_OFED
Documentation updtes require specific kernel,rdma_coreand FW versions as well as installation procedures. These details should be supplied by regression team.Moti Haimovsky (6):
net/mlx4: add simple Tx bypassing ibverbs
net/mlx4: get back Rx flow functionality
net/mlx4: support multi-segments Tx
net/mlx4: get back Tx checksum offloads
net/mlx4: get back Rx checksum offloads
net/mlx4: add loopback Tx from VF
Quoted 2 lines
Vasily Philipov (1):
net/mlx4: support multi-segments Rx
Adried looks like beat you with a few hours :)
Can you please clarify which set is valid one, thanks.
Re: [PATCH v3 0/7] new mlx4 datapath bypassing ibverbs
05/10/2017 00:37, Ferruh Yigit:
Quoted 9 lines · Ophir Munk
Quoted 8 lines
Moti Haimovsky (6):
net/mlx4: add simple Tx bypassing ibverbs
net/mlx4: get back Rx flow functionality
net/mlx4: support multi-segments Tx
net/mlx4: get back Tx checksum offloads
net/mlx4: get back Rx checksum offloads
net/mlx4: add loopback Tx from VF
Quoted 6 lines
Quoted 2 lines
Vasily Philipov (1):
net/mlx4: support multi-segments RxAdried looks like beat you with a few hours :)
Can you please clarify which set is valid one, thanks.
I think we need a v4 merging both v3.
Hi Moti,
Small comments/question to clarify the situation for any user of this series.
Quoted 11 lines · Moti Haimovsky
This series of patches implements the mlx4-pmd with Tx data path that directly access the device queues for transmitting packets, bypassing the ibverbs Tx data path altogether.
Using this scheme allows the PMD to work with upstream rdma-core package instead of the Mellanox OFED one without sacrificing Tx functionality.These patches should be applied in the order listed below as each depends on its predecessor to work.
This implementation allows rapid deployment of new features without the need to update the underlying OFED.
Seems this explanation is wrong, the PMD still relies on Verbs for control plane configuration and thus for new features it will still require an update of the underlying layers i.e RDMA-Core or MLNX_OFED >= 4.2 and the associated Linux Kernel Mellanox drivers.
Quoted 11 lines
This work depends on
http://dpdk.org/ml/archives/dev/2017-August/072281.html
[dpdk-dev] [PATCH v1 00/48] net/mlx4: trim and refactor entire PMD
by Adrien MazarguilIt had been built and tested using rdma-core-15-1 from
https://github.com/linux-rdma/rdma-core
and kernel-ml-4.12.0-1.el7.elrepo.x86_64It had been built and tested using rdma-core-15-1 from
https://github.com/linux-rdma/rdma-core
Seems this version (15-1) does not exists on this repository the latest being v15.
Does this series compiles and work on this version, or should the user use some point above the v15?
Quoted 9 lines
and kernel-ml-4.12.0-1.el7.elrepo.x86_64
Moti Haimovsky (5):
net/mlx4: add simple Tx bypassing ibverbs
net/mlx4: support multi-segments Tx
net/mlx4: refine setting Tx completion flag
net/mlx4: add Tx checksum offloads
net/mlx4: add loopback Tx from VF
Quoted 13 lines
drivers/net/mlx4/mlx4.c | 7 + drivers/net/mlx4/mlx4.h | 2 + drivers/net/mlx4/mlx4_ethdev.c | 6 + drivers/net/mlx4/mlx4_prm.h | 249 ++++++++++++++++++++++ drivers/net/mlx4/mlx4_rxtx.c | 456 +++++++++++++++++++++++++++++++++-------- drivers/net/mlx4/mlx4_rxtx.h | 39 +++- drivers/net/mlx4/mlx4_txq.c | 66 +++++- mk/rte.app.mk | 2 +- 8 files changed, 734 insertions(+), 93 deletions(-) create mode 100644 drivers/net/mlx4/mlx4_prm.hSignature · 1 line
1.8.3.1
Thanks,
Signature · 2 lines
Nélio Laranjeiro 6WIND