[dpdk-dev] [PATCH 1/5] i40e: extract non-x86 specific code from vector driver
Zhang, Qi Z
qi.z.zhang at intel.com
Wed Oct 12 04:55:32 CEST 2016
Hi Jianbo
> -----Original Message-----
> From: dev [mailto:dev-bounces at dpdk.org] On Behalf Of Jianbo Liu
> Sent: Wednesday, August 24, 2016 5:54 PM
> To: Zhang, Helin <helin.zhang at intel.com>; Wu, Jingjing
> <jingjing.wu at intel.com>; jerin.jacob at caviumnetworks.com; dev at dpdk.org
> Cc: Jianbo Liu <jianbo.liu at linaro.org>
> Subject: [dpdk-dev] [PATCH 1/5] i40e: extract non-x86 specific code from vector
> driver
>
> move scalar code which does not use x86 intrinsic functions to new file
> "i40e_rxtx_vec_common.h", while keeping x86 code in i40e_rxtx_vec.c.
> This allows the scalar code to to be shared among vector drivers for different
> platforms.
>
> Signed-off-by: Jianbo Liu <jianbo.liu at linaro.org>
> ---
> drivers/net/i40e/i40e_rxtx_vec.c | 184 +-----------------------
> drivers/net/i40e/i40e_rxtx_vec_common.h | 239
> ++++++++++++++++++++++++++++++++
> 2 files changed, 243 insertions(+), 180 deletions(-) create mode 100644
> drivers/net/i40e/i40e_rxtx_vec_common.h
>
> diff --git a/drivers/net/i40e/i40e_rxtx_vec.c b/drivers/net/i40e/i40e_rxtx_vec.c
> index 51fb282..f847469 100644
> --- a/drivers/net/i40e/i40e_rxtx_vec.c
> +++ b/drivers/net/i40e/i40e_rxtx_vec.c
> @@ -39,6 +39,7 @@
> #include "base/i40e_type.h"
> #include "i40e_ethdev.h"
> #include "i40e_rxtx.h"
> +#include "i40e_rxtx_vec_common.h"
>
> #include <tmmintrin.h>
>
> @@ -421,68 +422,6 @@ i40e_recv_pkts_vec(void *rx_queue, struct rte_mbuf
> **rx_pkts,
> return _recv_raw_pkts_vec(rx_queue, rx_pkts, nb_pkts, NULL); }
>
> -static inline uint16_t
> -reassemble_packets(struct i40e_rx_queue *rxq, struct rte_mbuf **rx_bufs,
> - uint16_t nb_bufs, uint8_t *split_flags)
> -{
> - struct rte_mbuf *pkts[RTE_I40E_VPMD_RX_BURST]; /*finished pkts*/
> - struct rte_mbuf *start = rxq->pkt_first_seg;
> - struct rte_mbuf *end = rxq->pkt_last_seg;
> - unsigned pkt_idx, buf_idx;
> -
> - for (buf_idx = 0, pkt_idx = 0; buf_idx < nb_bufs; buf_idx++) {
> - if (end != NULL) {
> - /* processing a split packet */
> - end->next = rx_bufs[buf_idx];
> - rx_bufs[buf_idx]->data_len += rxq->crc_len;
> -
> - start->nb_segs++;
> - start->pkt_len += rx_bufs[buf_idx]->data_len;
> - end = end->next;
> -
> - if (!split_flags[buf_idx]) {
> - /* it's the last packet of the set */
> - start->hash = end->hash;
> - start->ol_flags = end->ol_flags;
> - /* we need to strip crc for the whole packet */
> - start->pkt_len -= rxq->crc_len;
> - if (end->data_len > rxq->crc_len) {
> - end->data_len -= rxq->crc_len;
> - } else {
> - /* free up last mbuf */
> - struct rte_mbuf *secondlast = start;
> -
> - while (secondlast->next != end)
> - secondlast = secondlast->next;
> - secondlast->data_len -= (rxq->crc_len -
> - end->data_len);
> - secondlast->next = NULL;
> - rte_pktmbuf_free_seg(end);
> - end = secondlast;
> - }
> - pkts[pkt_idx++] = start;
> - start = end = NULL;
> - }
> - } else {
> - /* not processing a split packet */
> - if (!split_flags[buf_idx]) {
> - /* not a split packet, save and skip */
> - pkts[pkt_idx++] = rx_bufs[buf_idx];
> - continue;
> - }
> - end = start = rx_bufs[buf_idx];
> - rx_bufs[buf_idx]->data_len += rxq->crc_len;
> - rx_bufs[buf_idx]->pkt_len += rxq->crc_len;
> - }
> - }
> -
> - /* save the partial packet for next time */
> - rxq->pkt_first_seg = start;
> - rxq->pkt_last_seg = end;
> - memcpy(rx_bufs, pkts, pkt_idx * (sizeof(*pkts)));
> - return pkt_idx;
> -}
> -
> /* vPMD receive routine that reassembles scattered packets
> * Notice:
> * - nb_pkts < RTE_I40E_DESCS_PER_LOOP, just return no packet @@
> -548,73 +487,6 @@ vtx(volatile struct i40e_tx_desc *txdp,
> vtx1(txdp, *pkt, flags);
> }
>
> -static inline int __attribute__((always_inline)) -i40e_tx_free_bufs(struct
> i40e_tx_queue *txq) -{
> - struct i40e_tx_entry *txep;
> - uint32_t n;
> - uint32_t i;
> - int nb_free = 0;
> - struct rte_mbuf *m, *free[RTE_I40E_TX_MAX_FREE_BUF_SZ];
> -
> - /* check DD bits on threshold descriptor */
> - if ((txq->tx_ring[txq->tx_next_dd].cmd_type_offset_bsz &
> - rte_cpu_to_le_64(I40E_TXD_QW1_DTYPE_MASK)) !=
> - rte_cpu_to_le_64(I40E_TX_DESC_DTYPE_DESC_DONE))
> - return 0;
> -
> - n = txq->tx_rs_thresh;
> -
> - /* first buffer to free from S/W ring is at index
> - * tx_next_dd - (tx_rs_thresh-1)
> - */
> - txep = &txq->sw_ring[txq->tx_next_dd - (n - 1)];
> - m = __rte_pktmbuf_prefree_seg(txep[0].mbuf);
> - if (likely(m != NULL)) {
> - free[0] = m;
> - nb_free = 1;
> - for (i = 1; i < n; i++) {
> - m = __rte_pktmbuf_prefree_seg(txep[i].mbuf);
> - if (likely(m != NULL)) {
> - if (likely(m->pool == free[0]->pool)) {
> - free[nb_free++] = m;
> - } else {
> - rte_mempool_put_bulk(free[0]->pool,
> - (void *)free,
> - nb_free);
> - free[0] = m;
> - nb_free = 1;
> - }
> - }
> - }
> - rte_mempool_put_bulk(free[0]->pool, (void **)free, nb_free);
> - } else {
> - for (i = 1; i < n; i++) {
> - m = __rte_pktmbuf_prefree_seg(txep[i].mbuf);
> - if (m != NULL)
> - rte_mempool_put(m->pool, m);
> - }
> - }
> -
> - /* buffers were freed, update counters */
> - txq->nb_tx_free = (uint16_t)(txq->nb_tx_free + txq->tx_rs_thresh);
> - txq->tx_next_dd = (uint16_t)(txq->tx_next_dd + txq->tx_rs_thresh);
> - if (txq->tx_next_dd >= txq->nb_tx_desc)
> - txq->tx_next_dd = (uint16_t)(txq->tx_rs_thresh - 1);
> -
> - return txq->tx_rs_thresh;
> -}
> -
> -static inline void __attribute__((always_inline)) -tx_backlog_entry(struct
> i40e_tx_entry *txep,
> - struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
> -{
> - int i;
> -
> - for (i = 0; i < (int)nb_pkts; ++i)
> - txep[i].mbuf = tx_pkts[i];
> -}
> -
> uint16_t
> i40e_xmit_pkts_vec(void *tx_queue, struct rte_mbuf **tx_pkts,
> uint16_t nb_pkts)
> @@ -685,37 +557,13 @@ i40e_xmit_pkts_vec(void *tx_queue, struct
> rte_mbuf **tx_pkts, void __attribute__((cold))
> i40e_rx_queue_release_mbufs_vec(struct i40e_rx_queue *rxq) {
> - const unsigned mask = rxq->nb_rx_desc - 1;
> - unsigned i;
> -
> - if (rxq->sw_ring == NULL || rxq->rxrearm_nb >= rxq->nb_rx_desc)
> - return;
> -
> - /* free all mbufs that are valid in the ring */
> - for (i = rxq->rx_tail; i != rxq->rxrearm_start; i = (i + 1) & mask)
> - rte_pktmbuf_free_seg(rxq->sw_ring[i].mbuf);
> - rxq->rxrearm_nb = rxq->nb_rx_desc;
> -
> - /* set all entries to NULL */
> - memset(rxq->sw_ring, 0, sizeof(rxq->sw_ring[0]) * rxq->nb_rx_desc);
> + _i40e_rx_queue_release_mbufs_vec(rxq);
> }
>
> int __attribute__((cold))
> i40e_rxq_vec_setup(struct i40e_rx_queue *rxq) {
> - uintptr_t p;
> - struct rte_mbuf mb_def = { .buf_addr = 0 }; /* zeroed mbuf */
> -
> - mb_def.nb_segs = 1;
> - mb_def.data_off = RTE_PKTMBUF_HEADROOM;
> - mb_def.port = rxq->port_id;
> - rte_mbuf_refcnt_set(&mb_def, 1);
> -
> - /* prevent compiler reordering: rearm_data covers previous fields */
> - rte_compiler_barrier();
> - p = (uintptr_t)&mb_def.rearm_data;
> - rxq->mbuf_initializer = *(uint64_t *)p;
> - return 0;
> + return i40e_rxq_vec_setup_default(rxq);
> }
>
> int __attribute__((cold))
> @@ -728,34 +576,10 @@ int __attribute__((cold))
> i40e_rx_vec_dev_conf_condition_check(struct rte_eth_dev *dev) { #ifndef
> RTE_LIBRTE_IEEE1588
> - struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode;
> - struct rte_fdir_conf *fconf = &dev->data->dev_conf.fdir_conf;
> -
> /* need SSE4.1 support */
> if (!rte_cpu_get_flag_enabled(RTE_CPUFLAG_SSE4_1))
> return -1;
> -
> -#ifndef RTE_LIBRTE_I40E_RX_OLFLAGS_ENABLE
> - /* whithout rx ol_flags, no VP flag report */
> - if (rxmode->hw_vlan_strip != 0 ||
> - rxmode->hw_vlan_extend != 0)
> - return -1;
> #endif
>
> - /* no fdir support */
> - if (fconf->mode != RTE_FDIR_MODE_NONE)
> - return -1;
> -
> - /* - no csum error report support
> - * - no header split support
> - */
> - if (rxmode->hw_ip_checksum == 1 ||
> - rxmode->header_split == 1)
> - return -1;
> -
> - return 0;
> -#else
> - RTE_SET_USED(dev);
> - return -1;
> -#endif
> + return i40e_rx_vec_dev_conf_condition_check_default(dev);
> }
> diff --git a/drivers/net/i40e/i40e_rxtx_vec_common.h
> b/drivers/net/i40e/i40e_rxtx_vec_common.h
> new file mode 100644
> index 0000000..b31b39e
> --- /dev/null
> +++ b/drivers/net/i40e/i40e_rxtx_vec_common.h
> @@ -0,0 +1,239 @@
> +/*-
> + * BSD LICENSE
> + *
> + * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
> + * All rights reserved.
> + *
> + * 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 Intel Corporation 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 _I40E_RXTX_VEC_COMMON_H_
> +#define _I40E_RXTX_VEC_COMMON_H_
> +#include <stdint.h>
> +#include <rte_ethdev.h>
> +#include <rte_malloc.h>
> +
> +#include "i40e_ethdev.h"
> +#include "i40e_rxtx.h"
> +
> +static inline uint16_t
> +reassemble_packets(struct i40e_rx_queue *rxq, struct rte_mbuf **rx_bufs,
> + uint16_t nb_bufs, uint8_t *split_flags) {
> + struct rte_mbuf *pkts[RTE_I40E_VPMD_RX_BURST]; /*finished pkts*/
> + struct rte_mbuf *start = rxq->pkt_first_seg;
> + struct rte_mbuf *end = rxq->pkt_last_seg;
> + unsigned pkt_idx, buf_idx;
> +
> + for (buf_idx = 0, pkt_idx = 0; buf_idx < nb_bufs; buf_idx++) {
> + if (end != NULL) {
> + /* processing a split packet */
> + end->next = rx_bufs[buf_idx];
> + rx_bufs[buf_idx]->data_len += rxq->crc_len;
> +
> + start->nb_segs++;
> + start->pkt_len += rx_bufs[buf_idx]->data_len;
> + end = end->next;
> +
> + if (!split_flags[buf_idx]) {
> + /* it's the last packet of the set */
> + start->hash = end->hash;
> + start->ol_flags = end->ol_flags;
> + /* we need to strip crc for the whole packet */
> + start->pkt_len -= rxq->crc_len;
> + if (end->data_len > rxq->crc_len) {
> + end->data_len -= rxq->crc_len;
> + } else {
> + /* free up last mbuf */
> + struct rte_mbuf *secondlast = start;
> +
> + while (secondlast->next != end)
> + secondlast = secondlast->next;
> + secondlast->data_len -= (rxq->crc_len -
> + end->data_len);
> + secondlast->next = NULL;
> + rte_pktmbuf_free_seg(end);
> + end = secondlast;
> + }
> + pkts[pkt_idx++] = start;
> + start = end = NULL;
> + }
> + } else {
> + /* not processing a split packet */
> + if (!split_flags[buf_idx]) {
> + /* not a split packet, save and skip */
> + pkts[pkt_idx++] = rx_bufs[buf_idx];
> + continue;
> + }
> + end = start = rx_bufs[buf_idx];
> + rx_bufs[buf_idx]->data_len += rxq->crc_len;
> + rx_bufs[buf_idx]->pkt_len += rxq->crc_len;
> + }
> + }
> +
> + /* save the partial packet for next time */
> + rxq->pkt_first_seg = start;
> + rxq->pkt_last_seg = end;
> + memcpy(rx_bufs, pkts, pkt_idx * (sizeof(*pkts)));
> + return pkt_idx;
> +}
> +
> +static inline int __attribute__((always_inline))
> +i40e_tx_free_bufs(struct i40e_tx_queue *txq) {
> + struct i40e_tx_entry *txep;
> + uint32_t n;
> + uint32_t i;
> + int nb_free = 0;
> + struct rte_mbuf *m, *free[RTE_I40E_TX_MAX_FREE_BUF_SZ];
> +
> + /* check DD bits on threshold descriptor */
> + if ((txq->tx_ring[txq->tx_next_dd].cmd_type_offset_bsz &
> + rte_cpu_to_le_64(I40E_TXD_QW1_DTYPE_MASK)) !=
> + rte_cpu_to_le_64(I40E_TX_DESC_DTYPE_DESC_DONE))
> + return 0;
> +
> + n = txq->tx_rs_thresh;
> +
> + /* first buffer to free from S/W ring is at index
> + * tx_next_dd - (tx_rs_thresh-1)
> + */
> + txep = &txq->sw_ring[txq->tx_next_dd - (n - 1)];
> + m = __rte_pktmbuf_prefree_seg(txep[0].mbuf);
> + if (likely(m != NULL)) {
> + free[0] = m;
> + nb_free = 1;
> + for (i = 1; i < n; i++) {
> + m = __rte_pktmbuf_prefree_seg(txep[i].mbuf);
> + if (likely(m != NULL)) {
> + if (likely(m->pool == free[0]->pool)) {
> + free[nb_free++] = m;
> + } else {
> + rte_mempool_put_bulk(free[0]->pool,
> + (void *)free,
> + nb_free);
> + free[0] = m;
> + nb_free = 1;
> + }
> + }
> + }
> + rte_mempool_put_bulk(free[0]->pool, (void **)free, nb_free);
> + } else {
> + for (i = 1; i < n; i++) {
> + m = __rte_pktmbuf_prefree_seg(txep[i].mbuf);
> + if (m != NULL)
> + rte_mempool_put(m->pool, m);
> + }
> + }
> +
> + /* buffers were freed, update counters */
> + txq->nb_tx_free = (uint16_t)(txq->nb_tx_free + txq->tx_rs_thresh);
> + txq->tx_next_dd = (uint16_t)(txq->tx_next_dd + txq->tx_rs_thresh);
> + if (txq->tx_next_dd >= txq->nb_tx_desc)
> + txq->tx_next_dd = (uint16_t)(txq->tx_rs_thresh - 1);
> +
> + return txq->tx_rs_thresh;
> +}
> +
> +static inline void __attribute__((always_inline))
> +tx_backlog_entry(struct i40e_tx_entry *txep,
> + struct rte_mbuf **tx_pkts, uint16_t nb_pkts) {
> + int i;
> +
> + for (i = 0; i < (int)nb_pkts; ++i)
> + txep[i].mbuf = tx_pkts[i];
> +}
> +
> +static inline void
> +_i40e_rx_queue_release_mbufs_vec(struct i40e_rx_queue *rxq) {
> + const unsigned mask = rxq->nb_rx_desc - 1;
> + unsigned i;
> +
> + if (rxq->sw_ring == NULL || rxq->rxrearm_nb >= rxq->nb_rx_desc)
> + return;
> +
> + /* free all mbufs that are valid in the ring */
> + for (i = rxq->rx_tail; i != rxq->rxrearm_start; i = (i + 1) & mask)
> + rte_pktmbuf_free_seg(rxq->sw_ring[i].mbuf);
> + rxq->rxrearm_nb = rxq->nb_rx_desc;
> +
> + /* set all entries to NULL */
> + memset(rxq->sw_ring, 0, sizeof(rxq->sw_ring[0]) * rxq->nb_rx_desc); }
> +
> +static inline int
> +i40e_rxq_vec_setup_default(struct i40e_rx_queue *rxq) {
> + uintptr_t p;
> + struct rte_mbuf mb_def = { .buf_addr = 0 }; /* zeroed mbuf */
> +
> + mb_def.nb_segs = 1;
> + mb_def.data_off = RTE_PKTMBUF_HEADROOM;
> + mb_def.port = rxq->port_id;
> + rte_mbuf_refcnt_set(&mb_def, 1);
> +
> + /* prevent compiler reordering: rearm_data covers previous fields */
> + rte_compiler_barrier();
> + p = (uintptr_t)&mb_def.rearm_data;
> + rxq->mbuf_initializer = *(uint64_t *)p;
> + return 0;
> +}
> +
> +static inline int
> +i40e_rx_vec_dev_conf_condition_check_default(struct rte_eth_dev *dev) {
> +#ifndef RTE_LIBRTE_IEEE1588
> + struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode;
> + struct rte_fdir_conf *fconf = &dev->data->dev_conf.fdir_conf;
> +
> +#ifndef RTE_LIBRTE_I40E_RX_OLFLAGS_ENABLE
> + /* whithout rx ol_flags, no VP flag report */
> + if (rxmode->hw_vlan_strip != 0 ||
> + rxmode->hw_vlan_extend != 0)
> + return -1;
> +#endif
> +
> + /* no fdir support */
> + if (fconf->mode != RTE_FDIR_MODE_NONE)
> + return -1;
> +
> + /* - no csum error report support
> + * - no header split support
> + */
> + if (rxmode->hw_ip_checksum == 1 ||
> + rxmode->header_split == 1)
> + return -1;
> +
> + return 0;
> +#else
> + RTE_SET_USED(dev);
> + return -1;
> +#endif
> +}
> +#endif
> --
> 2.4.11
Should we rename the function "_40e_rx_queue_release_mbufs_vec" to
"i40e_rx_queue_release_mbufs_vec_default", so functions be wrapped can follow a consistent rule?
Thanks!
Qi
More information about the dev
mailing list