net/enic: add simple Rx handler
authorJohn Daley <johndale@cisco.com>
Fri, 29 Jun 2018 09:29:42 +0000 (02:29 -0700)
committerFerruh Yigit <ferruh.yigit@intel.com>
Mon, 2 Jul 2018 23:54:26 +0000 (01:54 +0200)
Add an optimized Rx handler for non-scattered Rx.

Signed-off-by: Hyong Youb Kim <hyonkim@cisco.com>
Signed-off-by: John Daley <johndale@cisco.com>
drivers/net/enic/base/cq_desc.h
drivers/net/enic/base/vnic_rq.h
drivers/net/enic/enic.h
drivers/net/enic/enic_ethdev.c
drivers/net/enic/enic_main.c
drivers/net/enic/enic_res.h
drivers/net/enic/enic_rxtx.c

index 7e13802..ae8847c 100644 (file)
@@ -38,6 +38,7 @@ struct cq_desc {
 #define CQ_DESC_TYPE_MASK        ((1 << CQ_DESC_TYPE_BITS) - 1)
 #define CQ_DESC_COLOR_MASK       1
 #define CQ_DESC_COLOR_SHIFT      7
+#define CQ_DESC_COLOR_MASK_NOSHIFT 0x80
 #define CQ_DESC_Q_NUM_BITS       10
 #define CQ_DESC_Q_NUM_MASK       ((1 << CQ_DESC_Q_NUM_BITS) - 1)
 #define CQ_DESC_COMP_NDX_BITS    12
index 9619290..d8e67f7 100644 (file)
@@ -52,6 +52,8 @@ struct vnic_rq {
        struct vnic_dev *vdev;
        struct vnic_rq_ctrl __iomem *ctrl;      /* memory-mapped */
        struct vnic_dev_ring ring;
+       struct rte_mbuf **free_mbufs;           /* reserve of free mbufs */
+       int num_free_mbufs;
        struct rte_mbuf **mbuf_ring;            /* array of allocated mbufs */
        unsigned int mbuf_next_idx;             /* next mb to consume */
        void *os_buf_head;
index a40ea79..7c27bd5 100644 (file)
@@ -313,6 +313,8 @@ int enic_clsf_init(struct enic *enic);
 void enic_clsf_destroy(struct enic *enic);
 uint16_t enic_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
                        uint16_t nb_pkts);
+uint16_t enic_noscatter_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
+                                 uint16_t nb_pkts);
 uint16_t enic_dummy_recv_pkts(void *rx_queue,
                              struct rte_mbuf **rx_pkts,
                              uint16_t nb_pkts);
index 15d9371..28bd0ff 100644 (file)
@@ -524,7 +524,8 @@ static const uint32_t *enicpmd_dev_supported_ptypes_get(struct rte_eth_dev *dev)
                RTE_PTYPE_UNKNOWN
        };
 
-       if (dev->rx_pkt_burst == enic_recv_pkts)
+       if (dev->rx_pkt_burst == enic_recv_pkts ||
+           dev->rx_pkt_burst == enic_noscatter_recv_pkts)
                return ptypes;
        return NULL;
 }
index e89105d..c8456c4 100644 (file)
@@ -571,6 +571,14 @@ int enic_enable(struct enic *enic)
                eth_dev->tx_pkt_burst = &enic_xmit_pkts;
        }
 
+       /* Use the non-scatter, simplified RX handler if possible. */
+       if (enic->rq_count > 0 && enic->rq[0].data_queue_enable == 0) {
+               PMD_INIT_LOG(DEBUG, " use the non-scatter Rx handler");
+               eth_dev->rx_pkt_burst = &enic_noscatter_recv_pkts;
+       } else {
+               PMD_INIT_LOG(DEBUG, " use the normal Rx handler");
+       }
+
        for (index = 0; index < enic->wq_count; index++)
                enic_start_wq(enic, index);
        for (index = 0; index < enic->rq_count; index++)
@@ -623,6 +631,19 @@ void enic_free_rq(void *rxq)
        enic = vnic_dev_priv(rq_sop->vdev);
        rq_data = &enic->rq[rq_sop->data_queue_idx];
 
+       if (rq_sop->free_mbufs) {
+               struct rte_mbuf **mb;
+               int i;
+
+               mb = rq_sop->free_mbufs;
+               for (i = ENIC_RX_BURST_MAX - rq_sop->num_free_mbufs;
+                    i < ENIC_RX_BURST_MAX; i++)
+                       rte_pktmbuf_free(mb[i]);
+               rte_free(rq_sop->free_mbufs);
+               rq_sop->free_mbufs = NULL;
+               rq_sop->num_free_mbufs = 0;
+       }
+
        enic_rxmbuf_queue_release(enic, rq_sop);
        if (rq_data->in_use)
                enic_rxmbuf_queue_release(enic, rq_data);
@@ -786,13 +807,13 @@ int enic_alloc_rq(struct enic *enic, uint16_t queue_idx,
        rq_data->max_mbufs_per_pkt = mbufs_per_pkt;
 
        if (mbufs_per_pkt > 1) {
-               min_sop = 64;
+               min_sop = ENIC_RX_BURST_MAX;
                max_sop = ((enic->config.rq_desc_count /
                            (mbufs_per_pkt - 1)) & ENIC_ALIGN_DESCS_MASK);
                min_data = min_sop * (mbufs_per_pkt - 1);
                max_data = enic->config.rq_desc_count;
        } else {
-               min_sop = 64;
+               min_sop = ENIC_RX_BURST_MAX;
                max_sop = enic->config.rq_desc_count;
                min_data = 0;
                max_data = 0;
@@ -863,10 +884,21 @@ int enic_alloc_rq(struct enic *enic, uint16_t queue_idx,
                        goto err_free_sop_mbuf;
        }
 
+       rq_sop->free_mbufs = (struct rte_mbuf **)
+               rte_zmalloc_socket("rq->free_mbufs",
+                                  sizeof(struct rte_mbuf *) *
+                                  ENIC_RX_BURST_MAX,
+                                  RTE_CACHE_LINE_SIZE, rq_sop->socket_id);
+       if (rq_sop->free_mbufs == NULL)
+               goto err_free_data_mbuf;
+       rq_sop->num_free_mbufs = 0;
+
        rq_sop->tot_nb_desc = nb_desc; /* squirl away for MTU update function */
 
        return 0;
 
+err_free_data_mbuf:
+       rte_free(rq_data->mbuf_ring);
 err_free_sop_mbuf:
        rte_free(rq_sop->mbuf_ring);
 err_free_cq:
index 6b1f6ac..3786bc0 100644 (file)
@@ -37,6 +37,7 @@
 #define ENIC_NON_TSO_MAX_DESC          16
 #define ENIC_DEFAULT_RX_FREE_THRESH    32
 #define ENIC_TX_XMIT_MAX               64
+#define ENIC_RX_BURST_MAX              64
 
 /* Defaults for dev_info.default_{rx,tx}portconf */
 #define ENIC_DEFAULT_RX_BURST          32
index 04a77fc..e0f93dd 100644 (file)
@@ -471,6 +471,120 @@ enic_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
        return nb_rx;
 }
 
+uint16_t
+enic_noscatter_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
+                        uint16_t nb_pkts)
+{
+       struct rte_mbuf *mb, **rx, **rxmb;
+       uint16_t cq_idx, nb_rx, max_rx;
+       struct cq_enet_rq_desc *cqd;
+       struct rq_enet_desc *rqd;
+       unsigned int port_id;
+       struct vnic_cq *cq;
+       struct vnic_rq *rq;
+       struct enic *enic;
+       uint8_t color;
+       bool overlay;
+       bool tnl;
+
+       rq = rx_queue;
+       enic = vnic_dev_priv(rq->vdev);
+       cq = &enic->cq[enic_cq_rq(enic, rq->index)];
+       cq_idx = cq->to_clean;
+
+       /*
+        * Fill up the reserve of free mbufs. Below, we restock the receive
+        * ring with these mbufs to avoid allocation failures.
+        */
+       if (rq->num_free_mbufs == 0) {
+               if (rte_mempool_get_bulk(rq->mp, (void **)rq->free_mbufs,
+                                        ENIC_RX_BURST_MAX))
+                       return 0;
+               rq->num_free_mbufs = ENIC_RX_BURST_MAX;
+       }
+
+       /* Receive until the end of the ring, at most. */
+       max_rx = RTE_MIN(nb_pkts, rq->num_free_mbufs);
+       max_rx = RTE_MIN(max_rx, cq->ring.desc_count - cq_idx);
+
+       cqd = (struct cq_enet_rq_desc *)(cq->ring.descs) + cq_idx;
+       color = cq->last_color;
+       rxmb = rq->mbuf_ring + cq_idx;
+       port_id = enic->port_id;
+       overlay = enic->overlay_offload;
+
+       rx = rx_pkts;
+       while (max_rx) {
+               max_rx--;
+               if ((cqd->type_color & CQ_DESC_COLOR_MASK_NOSHIFT) == color)
+                       break;
+               if (unlikely(cqd->bytes_written_flags &
+                            CQ_ENET_RQ_DESC_FLAGS_TRUNCATED)) {
+                       rte_pktmbuf_free(*rxmb++);
+                       rte_atomic64_inc(&enic->soft_stats.rx_packet_errors);
+                       cqd++;
+                       continue;
+               }
+
+               mb = *rxmb++;
+               /* prefetch mbuf data for caller */
+               rte_packet_prefetch(RTE_PTR_ADD(mb->buf_addr,
+                                   RTE_PKTMBUF_HEADROOM));
+               mb->data_len = cqd->bytes_written_flags &
+                       CQ_ENET_RQ_DESC_BYTES_WRITTEN_MASK;
+               mb->pkt_len = mb->data_len;
+               mb->port = port_id;
+               tnl = overlay && (cqd->completed_index_flags &
+                                 CQ_ENET_RQ_DESC_FLAGS_FCOE) != 0;
+               mb->packet_type =
+                       enic_cq_rx_flags_to_pkt_type((struct cq_desc *)cqd,
+                                                    tnl);
+               enic_cq_rx_to_pkt_flags((struct cq_desc *)cqd, mb);
+               /* Wipe the outer types set by enic_cq_rx_flags_to_pkt_type() */
+               if (tnl) {
+                       mb->packet_type &= ~(RTE_PTYPE_L3_MASK |
+                                            RTE_PTYPE_L4_MASK);
+               }
+               cqd++;
+               *rx++ = mb;
+       }
+       /* Number of descriptors visited */
+       nb_rx = cqd - (struct cq_enet_rq_desc *)(cq->ring.descs) - cq_idx;
+       if (nb_rx == 0)
+               return 0;
+       rqd = ((struct rq_enet_desc *)rq->ring.descs) + cq_idx;
+       rxmb = rq->mbuf_ring + cq_idx;
+       cq_idx += nb_rx;
+       rq->rx_nb_hold += nb_rx;
+       if (unlikely(cq_idx == cq->ring.desc_count)) {
+               cq_idx = 0;
+               cq->last_color ^= CQ_DESC_COLOR_MASK_NOSHIFT;
+       }
+       cq->to_clean = cq_idx;
+
+       memcpy(rxmb, rq->free_mbufs + ENIC_RX_BURST_MAX - rq->num_free_mbufs,
+              sizeof(struct rte_mbuf *) * nb_rx);
+       rq->num_free_mbufs -= nb_rx;
+       while (nb_rx) {
+               nb_rx--;
+               mb = *rxmb++;
+               mb->data_off = RTE_PKTMBUF_HEADROOM;
+               rqd->address = mb->buf_iova + RTE_PKTMBUF_HEADROOM;
+               rqd++;
+       }
+       if (rq->rx_nb_hold > rq->rx_free_thresh) {
+               rq->posted_index = enic_ring_add(rq->ring.desc_count,
+                                                rq->posted_index,
+                                                rq->rx_nb_hold);
+               rq->rx_nb_hold = 0;
+               rte_wmb();
+               iowrite32_relaxed(rq->posted_index,
+                                 &rq->ctrl->posted_index);
+       }
+
+       return rx - rx_pkts;
+}
+
 static void enic_fast_free_wq_bufs(struct vnic_wq *wq, u16 completed_index)
 {
        unsigned int desc_count, n, nb_to_free, tail_idx;