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