[dpdk-dev] [PATCH v2 14/40] bnxt: initial Rx ring code

Stephen Hurd stephen.hurd at broadcom.com
Sat May 14 00:46:03 CEST 2016


Initial implementation of rx_pkt_burst
Add code to allocate rings to bnxt_ring.c

Signed-off-by: Stephen Hurd <stephen.hurd at broadcom.com>
Reviewed-by: Ajit Kumar Khaparde <ajit.khaparde at broadcom.com>
---
 drivers/net/bnxt/Makefile              |   1 +
 drivers/net/bnxt/bnxt_ethdev.c         |   3 +-
 drivers/net/bnxt/bnxt_ring.c           |  20 +-
 drivers/net/bnxt/bnxt_rxq.c            |  34 ++-
 drivers/net/bnxt/bnxt_rxr.c            | 338 +++++++++++++++++++++++
 drivers/net/bnxt/bnxt_rxr.h            |  62 +++++
 drivers/net/bnxt/hsi_struct_def_dpdk.h | 474 +++++++++++++++++++++++++++++++++
 7 files changed, 915 insertions(+), 17 deletions(-)
 create mode 100644 drivers/net/bnxt/bnxt_rxr.c
 create mode 100644 drivers/net/bnxt/bnxt_rxr.h

diff --git a/drivers/net/bnxt/Makefile b/drivers/net/bnxt/Makefile
index 0785681..4d35412 100644
--- a/drivers/net/bnxt/Makefile
+++ b/drivers/net/bnxt/Makefile
@@ -54,6 +54,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += bnxt_filter.c
 SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += bnxt_hwrm.c
 SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += bnxt_ring.c
 SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += bnxt_rxq.c
+SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += bnxt_rxr.c
 SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += bnxt_stats.c
 SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += bnxt_txq.c
 SRCS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += bnxt_txr.c
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index 61e856a..e1b3e3a 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -42,6 +42,7 @@
 #include "bnxt.h"
 #include "bnxt_hwrm.h"
 #include "bnxt_rxq.h"
+#include "bnxt_rxr.h"
 #include "bnxt_stats.h"
 #include "bnxt_txq.h"
 #include "bnxt_txr.h"
@@ -260,7 +261,7 @@ bnxt_dev_init(struct rte_eth_dev *eth_dev)
 		goto error;
 	}
 	eth_dev->dev_ops = &bnxt_dev_ops;
-	/* eth_dev->rx_pkt_burst = &bnxt_recv_pkts; */
+	eth_dev->rx_pkt_burst = &bnxt_recv_pkts;
 	eth_dev->tx_pkt_burst = &bnxt_xmit_pkts;
 
 	rc = bnxt_alloc_hwrm_resources(bp);
diff --git a/drivers/net/bnxt/bnxt_ring.c b/drivers/net/bnxt/bnxt_ring.c
index bb20806..69837bf 100644
--- a/drivers/net/bnxt/bnxt_ring.c
+++ b/drivers/net/bnxt/bnxt_ring.c
@@ -36,6 +36,7 @@
 #include "bnxt.h"
 #include "bnxt_cpr.h"
 #include "bnxt_ring.h"
+#include "bnxt_rxr.h"
 #include "bnxt_txr.h"
 
 #include "hsi_struct_def_dpdk.h"
@@ -77,9 +78,8 @@ int bnxt_alloc_rings(struct bnxt *bp, uint16_t qidx,
 			    const char *suffix)
 {
 	struct bnxt_ring_struct *cp_ring = cp_ring_info->cp_ring_struct;
+	struct bnxt_ring_struct *rx_ring;
 	struct bnxt_ring_struct *tx_ring;
-	/* TODO: RX ring */
-	/* struct bnxt_ring_struct *rx_ring; */
 	struct rte_pci_device *pdev = bp->pdev;
 	const struct rte_memzone *mz = NULL;
 	char mz_name[RTE_MEMZONE_NAMESIZE];
@@ -96,10 +96,9 @@ int bnxt_alloc_rings(struct bnxt *bp, uint16_t qidx,
 						tx_ring_struct->vmem_size) : 0;
 
 	int rx_vmem_start = tx_vmem_start + tx_vmem_len;
-	/* TODO: RX ring */
-	int rx_vmem_len = /*
-	    rx_ring_info ? RTE_CACHE_LINE_ROUNDUP(rx_ring_info->
-					rx_ring_struct->vmem_size) : */ 0;
+	int rx_vmem_len =
+		rx_ring_info ? RTE_CACHE_LINE_ROUNDUP(rx_ring_info->
+					rx_ring_struct->vmem_size) : 0;
 
 	int cp_ring_start = rx_vmem_start + rx_vmem_len;
 	int cp_ring_len = RTE_CACHE_LINE_ROUNDUP(cp_ring->ring_size *
@@ -111,10 +110,9 @@ int bnxt_alloc_rings(struct bnxt *bp, uint16_t qidx,
 				   sizeof(struct tx_bd_long)) : 0;
 
 	int rx_ring_start = tx_ring_start + tx_ring_len;
-	/* TODO: RX ring */
-	int rx_ring_len = /* rx_ring_info ?
+	int rx_ring_len = rx_ring_info ?
 	    RTE_CACHE_LINE_ROUNDUP(rx_ring_info->rx_ring_struct->ring_size *
-				   sizeof(struct rx_prod_pkt_bd)) : */ 0;
+				   sizeof(struct rx_prod_pkt_bd)) : 0;
 
 	int total_alloc_len = rx_ring_start + rx_ring_len;
 
@@ -152,9 +150,8 @@ int bnxt_alloc_rings(struct bnxt *bp, uint16_t qidx,
 		}
 	}
 
-/*
 	if (rx_ring_info) {
-		rx_ring = &rx_ring_info->rx_ring_struct;
+		rx_ring = rx_ring_info->rx_ring_struct;
 
 		rx_ring->bd = ((char *)mz->addr + rx_ring_start);
 		rx_ring_info->rx_desc_ring =
@@ -171,7 +168,6 @@ int bnxt_alloc_rings(struct bnxt *bp, uint16_t qidx,
 			    (struct bnxt_sw_rx_bd *)rx_ring->vmem;
 		}
 	}
-*/
 
 	cp_ring->bd = ((char *)mz->addr + cp_ring_start);
 	cp_ring->bd_dma = mz->phys_addr + cp_ring_start;
diff --git a/drivers/net/bnxt/bnxt_rxq.c b/drivers/net/bnxt/bnxt_rxq.c
index b284e20..90a116b 100644
--- a/drivers/net/bnxt/bnxt_rxq.c
+++ b/drivers/net/bnxt/bnxt_rxq.c
@@ -41,6 +41,7 @@
 #include "bnxt_hwrm.h"
 #include "bnxt_ring.h"
 #include "bnxt_rxq.h"
+#include "bnxt_rxr.h"
 #include "bnxt_vnic.h"
 #include "hsi_struct_def_dpdk.h"
 
@@ -215,7 +216,20 @@ err_out:
 
 static void bnxt_rx_queue_release_mbufs(struct bnxt_rx_queue *rxq __rte_unused)
 {
-	/* TODO: Requires interaction with TX ring */
+	struct bnxt_sw_rx_bd *sw_ring;
+	uint16_t i;
+
+	if (rxq) {
+		sw_ring = rxq->rx_ring->rx_buf_ring;
+		if (sw_ring) {
+			for (i = 0; i < rxq->nb_rx_desc; i++) {
+				if (sw_ring[i].mbuf) {
+					rte_pktmbuf_free_seg(sw_ring[i].mbuf);
+					sw_ring[i].mbuf = NULL;
+				}
+			}
+		}
+	}
 }
 
 void bnxt_free_rx_mbufs(struct bnxt *bp)
@@ -236,7 +250,13 @@ void bnxt_rx_queue_release_op(void *rx_queue)
 	if (rxq) {
 		bnxt_rx_queue_release_mbufs(rxq);
 
-		/* TODO: Free ring and stats here */
+		/* Free RX ring hardware descriptors */
+		bnxt_free_ring(rxq->rx_ring->rx_ring_struct);
+
+		/* Free RX completion ring hardware descriptors */
+		bnxt_free_ring(rxq->cp_ring->cp_ring_struct);
+
+		bnxt_free_rxq_stats(rxq);
 
 		rte_free(rxq);
 	}
@@ -273,7 +293,7 @@ int bnxt_rx_queue_setup_op(struct rte_eth_dev *eth_dev,
 	rxq->nb_rx_desc = nb_desc;
 	rxq->rx_free_thresh = rx_conf->rx_free_thresh;
 
-	/* TODO: Initialize ring structure */
+	bnxt_init_rx_ring_struct(rxq);
 
 	rxq->queue_id = queue_idx;
 	rxq->port_id = eth_dev->data->port_id;
@@ -281,7 +301,13 @@ int bnxt_rx_queue_setup_op(struct rte_eth_dev *eth_dev,
 				0 : ETHER_CRC_LEN);
 
 	eth_dev->data->rx_queues[queue_idx] = rxq;
-	/* TODO: Allocate RX ring hardware descriptors */
+	/* Allocate RX ring hardware descriptors */
+	if (bnxt_alloc_rings(bp, queue_idx, NULL, rxq->rx_ring, rxq->cp_ring,
+			"bnxt_rx_ring")) {
+		RTE_LOG(ERR, PMD, "ring_dma_zone_reserve for rx_ring failed!");
+		bnxt_rx_queue_release_op(rxq);
+		return -ENOMEM;
+	}
 
 	return 0;
 }
diff --git a/drivers/net/bnxt/bnxt_rxr.c b/drivers/net/bnxt/bnxt_rxr.c
new file mode 100644
index 0000000..eed88c6
--- /dev/null
+++ b/drivers/net/bnxt/bnxt_rxr.c
@@ -0,0 +1,338 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) Broadcom Limited.
+ *   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 Broadcom 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.
+ */
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <rte_byteorder.h>
+#include <rte_malloc.h>
+#include <rte_memory.h>
+
+#include "bnxt.h"
+#include "bnxt_cpr.h"
+#include "bnxt_ring.h"
+#include "bnxt_rxr.h"
+#include "bnxt_rxq.h"
+#include "hsi_struct_def_dpdk.h"
+
+/*
+ * RX Ring handling
+ */
+
+static inline struct rte_mbuf *__bnxt_alloc_rx_data(struct rte_mempool *mb)
+{
+	struct rte_mbuf *data;
+
+	data = __rte_mbuf_raw_alloc(mb);
+	__rte_mbuf_sanity_check(data, 0);
+
+	return data;
+}
+
+static inline int bnxt_alloc_rx_data(struct bnxt_rx_queue *rxq,
+				     struct bnxt_rx_ring_info *rxr,
+				     uint16_t prod)
+{
+	struct rx_prod_pkt_bd *rxbd = &rxr->rx_desc_ring[prod];
+	struct bnxt_sw_rx_bd *rx_buf = &rxr->rx_buf_ring[prod];
+	struct rte_mbuf *data;
+
+	data = __bnxt_alloc_rx_data(rxq->mb_pool);
+	if (!data)
+		return -ENOMEM;
+
+	rx_buf->mbuf = data;
+
+	rxbd->addr = rte_cpu_to_le_64(RTE_MBUF_DATA_DMA_ADDR(rx_buf->mbuf));
+
+	return 0;
+}
+
+static void bnxt_reuse_rx_mbuf(struct bnxt_rx_ring_info *rxr, uint16_t cons,
+			       struct rte_mbuf *mbuf)
+{
+	uint16_t prod = rxr->rx_prod;
+	struct bnxt_sw_rx_bd *prod_rx_buf;
+	struct rx_prod_pkt_bd *prod_bd, *cons_bd;
+
+	prod_rx_buf = &rxr->rx_buf_ring[prod];
+
+	prod_rx_buf->mbuf = mbuf;
+
+	prod_bd = &rxr->rx_desc_ring[prod];
+	cons_bd = &rxr->rx_desc_ring[cons];
+
+	prod_bd->addr = cons_bd->addr;
+}
+
+static uint16_t bnxt_rx_pkt(struct rte_mbuf **rx_pkt,
+			    struct bnxt_rx_queue *rxq, uint32_t *raw_cons)
+{
+	struct bnxt_cp_ring_info *cpr = rxq->cp_ring;
+	struct bnxt_rx_ring_info *rxr = rxq->rx_ring;
+	struct rx_pkt_cmpl *rxcmp;
+	struct rx_pkt_cmpl_hi *rxcmp1;
+	uint32_t tmp_raw_cons = *raw_cons;
+	uint16_t cons, prod, cp_cons =
+	    RING_CMP(cpr->cp_ring_struct, tmp_raw_cons);
+	struct bnxt_sw_rx_bd *rx_buf;
+	struct rte_mbuf *mbuf;
+	int rc = 0;
+
+	rxcmp = (struct rx_pkt_cmpl *)
+	    &cpr->cp_desc_ring[cp_cons];
+
+	tmp_raw_cons = NEXT_RAW_CMP(tmp_raw_cons);
+	cp_cons = RING_CMP(cpr->cp_ring_struct, tmp_raw_cons);
+	rxcmp1 = (struct rx_pkt_cmpl_hi *)&cpr->cp_desc_ring[cp_cons];
+
+	if (!CMP_VALID(rxcmp1, tmp_raw_cons, cpr->cp_ring_struct))
+		return -EBUSY;
+
+	prod = rxr->rx_prod;
+
+	/* EW - GRO deferred to phase 3 */
+	cons = rxcmp->opaque;
+	rx_buf = &rxr->rx_buf_ring[cons];
+	mbuf = rx_buf->mbuf;
+	rte_prefetch0(mbuf);
+
+	mbuf->nb_segs = 1;
+	mbuf->next = NULL;
+	mbuf->pkt_len = rxcmp->len;
+	mbuf->data_len = mbuf->pkt_len;
+	mbuf->port = rxq->port_id;
+	mbuf->ol_flags = 0;
+	if (rxcmp->flags_type & RX_PKT_CMPL_FLAGS_RSS_VALID) {
+		mbuf->hash.rss = rxcmp->rss_hash;
+		mbuf->ol_flags |= PKT_RX_RSS_HASH;
+	} else {
+		mbuf->hash.fdir.id = rxcmp1->cfa_code;
+		mbuf->ol_flags |= PKT_RX_FDIR | PKT_RX_FDIR_ID;
+	}
+	if (rxcmp1->flags2 & RX_PKT_CMPL_FLAGS2_META_FORMAT_VLAN) {
+		mbuf->vlan_tci = rxcmp1->metadata &
+			(RX_PKT_CMPL_METADATA_VID_MASK |
+			RX_PKT_CMPL_METADATA_DE |
+			RX_PKT_CMPL_METADATA_PRI_MASK);
+		mbuf->ol_flags |= PKT_RX_VLAN_PKT;
+	}
+
+	rx_buf->mbuf = NULL;
+	if (rxcmp1->errors_v2 & RX_CMP_L2_ERRORS) {
+		/* Re-install the mbuf back to the rx ring */
+		bnxt_reuse_rx_mbuf(rxr, cons, mbuf);
+
+		rc = -EIO;
+		goto next_rx;
+	}
+	/*
+	 * TODO: Redesign this....
+	 * If the allocation fails, the packet does not get received.
+	 * Simply returning this will result in slowly falling behind
+	 * on the producer ring buffers.
+	 * Instead, "filling up" the producer just before ringing the
+	 * doorbell could be a better solution since it will let the
+	 * producer ring starve until memory is available again pushing
+	 * the drops into hardware and getting them out of the driver
+	 * allowing recovery to a full producer ring.
+	 *
+	 * This could also help with cache usage by preventing per-packet
+	 * calls in favour of a tight loop with the same function being called
+	 * in it.
+	 */
+	if (bnxt_alloc_rx_data(rxq, rxr, prod)) {
+		RTE_LOG(ERR, PMD, "mbuf alloc failed with prod=0x%x\n", prod);
+		rc = -ENOMEM;
+		goto next_rx;
+	}
+
+	/* All MBUFs are allocated with the same size under DPDK,
+	   no optimization for rx_copy_thresh */
+
+	/* AGG buf operation is deferred */
+
+	/* EW - VLAN reception.  Must compare against the ol_flags */
+
+	*rx_pkt = mbuf;
+next_rx:
+	rxr->rx_prod = RING_NEXT(rxr->rx_ring_struct, prod);
+
+	*raw_cons = tmp_raw_cons;
+
+	return rc;
+}
+
+uint16_t bnxt_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
+			       uint16_t nb_pkts)
+{
+	struct bnxt_rx_queue *rxq = rx_queue;
+	struct bnxt_cp_ring_info *cpr = rxq->cp_ring;
+	struct bnxt_rx_ring_info *rxr = rxq->rx_ring;
+	uint32_t raw_cons = cpr->cp_raw_cons;
+	uint32_t cons;
+	int nb_rx_pkts = 0;
+	bool rx_event = false;
+	struct rx_pkt_cmpl *rxcmp;
+
+	/* Handle RX burst request */
+	while (1) {
+		int rc;
+
+		cons = RING_CMP(cpr->cp_ring_struct, raw_cons);
+		rte_prefetch0(&cpr->cp_desc_ring[cons]);
+		rxcmp = (struct rx_pkt_cmpl *)&cpr->cp_desc_ring[cons];
+
+		if (!CMP_VALID(rxcmp, raw_cons, cpr->cp_ring_struct))
+			break;
+
+		/* TODO: Avoid magic numbers... */
+		if ((CMP_TYPE(rxcmp) & 0x30) == 0x10) {
+			rc = bnxt_rx_pkt(&rx_pkts[nb_rx_pkts], rxq, &raw_cons);
+			if (likely(!rc))
+				nb_rx_pkts++;
+			else if (rc == -EBUSY)	/* partial completion */
+				break;
+			rx_event = true;
+		}
+		raw_cons = NEXT_RAW_CMP(raw_cons);
+		if (nb_rx_pkts == nb_pkts)
+			break;
+	}
+	if (raw_cons == cpr->cp_raw_cons) {
+		/* For PMD, there is no need to keep on pushing to REARM
+		   the doorbell if there are no new completions */
+		return nb_rx_pkts;
+	}
+	cpr->cp_raw_cons = raw_cons;
+
+	B_CP_DIS_DB(cpr, cpr->cp_raw_cons);
+	if (rx_event)
+		B_RX_DB(rxr->rx_doorbell, rxr->rx_prod);
+	return nb_rx_pkts;
+}
+
+void bnxt_free_rx_rings(struct bnxt *bp)
+{
+	int i;
+
+	for (i = 0; i < (int)bp->rx_nr_rings; i++) {
+		struct bnxt_rx_queue *rxq = bp->rx_queues[i];
+
+		if (!rxq)
+			continue;
+
+		/* TODO: free() rxq->rx_ring and rxq->rx_ring->rx_ring_struct */
+		bnxt_free_ring(rxq->rx_ring->rx_ring_struct);
+		/* TODO: free() rxq->cp_ring and rxq->cp_ring->cp_ring_struct */
+		bnxt_free_ring(rxq->cp_ring->cp_ring_struct);
+
+		rte_free(rxq);
+		bp->rx_queues[i] = NULL;
+	}
+}
+
+void bnxt_init_rx_ring_struct(struct bnxt_rx_queue *rxq)
+{
+	struct bnxt *bp = rxq->bp;
+	struct bnxt_cp_ring_info *cpr;
+	struct bnxt_rx_ring_info *rxr;
+	struct bnxt_ring_struct *ring;
+
+	rxq->rx_buf_use_size = bp->eth_dev->data->mtu +
+			       ETHER_HDR_LEN + ETHER_CRC_LEN +
+			       (2 * VLAN_TAG_SIZE);
+	rxq->rx_buf_size = rxq->rx_buf_use_size + sizeof(struct rte_mbuf);
+
+	rxr = rxq->rx_ring;
+	ring = rxr->rx_ring_struct;
+	ring->ring_size = rte_align32pow2(rxq->nb_rx_desc);
+	ring->ring_mask = ring->ring_size - 1;
+	ring->bd = (void *)rxr->rx_desc_ring;
+	ring->bd_dma = rxr->rx_desc_mapping;
+	ring->vmem_size = ring->ring_size * sizeof(struct bnxt_sw_rx_bd);
+	ring->vmem = (void **)&rxr->rx_buf_ring;
+
+	cpr = rxq->cp_ring;
+	ring = cpr->cp_ring_struct;
+	ring->ring_size = rxr->rx_ring_struct->ring_size * 2;
+	ring->ring_mask = ring->ring_size - 1;
+	ring->bd = (void *)cpr->cp_desc_ring;
+	ring->bd_dma = cpr->cp_desc_mapping;
+	ring->vmem_size = 0;
+	ring->vmem = NULL;
+}
+
+static void bnxt_init_rxbds(struct bnxt_ring_struct *ring, uint32_t type,
+			    uint16_t len)
+{
+	uint32_t j;
+	struct rx_prod_pkt_bd *rx_bd_ring = (struct rx_prod_pkt_bd *)ring->bd;
+
+	if (!rx_bd_ring)
+		return;
+	for (j = 0; j < ring->ring_size; j++) {
+		rx_bd_ring[j].flags_type = type;
+		rx_bd_ring[j].len = len;
+		rx_bd_ring[j].opaque = j;
+	}
+}
+
+int bnxt_init_one_rx_ring(struct bnxt_rx_queue *rxq)
+{
+	struct bnxt_rx_ring_info *rxr;
+	struct bnxt_ring_struct *ring;
+	uint32_t prod, type;
+	unsigned i;
+
+	type = RX_PROD_PKT_BD_TYPE_RX_PROD_PKT | RX_PROD_PKT_BD_FLAGS_EOP_PAD;
+
+	/* TODO: These need to be allocated */
+	rxr = rxq->rx_ring;
+	ring = rxr->rx_ring_struct;
+	bnxt_init_rxbds(ring, type, rxq->rx_buf_use_size);
+
+	prod = rxr->rx_prod;
+	for (i = 0; i < ring->ring_size; i++) {
+		if (bnxt_alloc_rx_data(rxq, rxr, prod) != 0) {
+			RTE_LOG(WARNING, PMD,
+				"init'ed rx ring %d with %d/%d mbufs only\n",
+				rxq->queue_id, i, ring->ring_size);
+			break;
+		}
+		rxr->rx_prod = prod;
+		prod = RING_NEXT(rxr->rx_ring_struct, prod);
+	}
+
+	return 0;
+}
diff --git a/drivers/net/bnxt/bnxt_rxr.h b/drivers/net/bnxt/bnxt_rxr.h
new file mode 100644
index 0000000..e9bae3f
--- /dev/null
+++ b/drivers/net/bnxt/bnxt_rxr.h
@@ -0,0 +1,62 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) Broadcom Limited.
+ *   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 Broadcom 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 _BNXT_RXR_H_
+#define _BNXT_RXR_H_
+
+#define B_RX_DB(db, prod)						\
+		(*(uint32_t *)db = (DB_KEY_RX | prod))
+
+struct bnxt_sw_rx_bd {
+	struct rte_mbuf		*mbuf; /* data associated with RX descriptor */
+};
+
+struct bnxt_rx_ring_info {
+	uint16_t		rx_prod;
+	void			*rx_doorbell;
+
+	struct rx_prod_pkt_bd	*rx_desc_ring;
+	struct bnxt_sw_rx_bd	*rx_buf_ring; /* sw ring */
+
+	phys_addr_t		rx_desc_mapping;
+
+	struct bnxt_ring_struct	*rx_ring_struct;
+};
+
+uint16_t bnxt_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
+			       uint16_t nb_pkts);
+void bnxt_free_rx_rings(struct bnxt *bp);
+void bnxt_init_rx_ring_struct(struct bnxt_rx_queue *rxq);
+int bnxt_init_one_rx_ring(struct bnxt_rx_queue *rxq);
+
+#endif
diff --git a/drivers/net/bnxt/hsi_struct_def_dpdk.h b/drivers/net/bnxt/hsi_struct_def_dpdk.h
index ff02a29..fd9eb62 100644
--- a/drivers/net/bnxt/hsi_struct_def_dpdk.h
+++ b/drivers/net/bnxt/hsi_struct_def_dpdk.h
@@ -446,6 +446,79 @@ struct tx_bd_long_hi {
 	uint32_t cfa_meta;
 } __attribute__((packed));
 
+/* RX Producer Packet BD (16 bytes) */
+struct rx_prod_pkt_bd {
+	/* This value identifies the type of buffer descriptor. */
+	#define RX_PROD_PKT_BD_TYPE_MASK		UINT32_C(0x3f)
+	#define RX_PROD_PKT_BD_TYPE_SFT			0
+		/*
+		 * Indicates that this BD is 16B long and is an RX Producer (ie.
+		 * empty) buffer descriptor.
+		 */
+	#define RX_PROD_PKT_BD_TYPE_RX_PROD_PKT		(UINT32_C(0x4) << 0)
+	/*
+	 * If set to 1, the packet will be placed at the address plus 2B. The 2
+	 * Bytes of padding will be written as zero.
+	 */
+	/*
+	 * This is intended to be used when the host buffer is cache-line
+	 * aligned to produce packets that are easy to parse in host memory
+	 * while still allowing writes to be cache line aligned.
+	 */
+	#define RX_PROD_PKT_BD_FLAGS_SOP_PAD		UINT32_C(0x40)
+	/*
+	 * If set to 1, the packet write will be padded out to the nearest
+	 * cache-line with zero value padding.
+	 */
+	/*
+	 * If receive buffers start/end on cache-line boundaries, this feature
+	 * will ensure that all data writes on the PCI bus start/end on cache
+	 * line boundaries.
+	 */
+	#define RX_PROD_PKT_BD_FLAGS_EOP_PAD		UINT32_C(0x80)
+	/*
+	 * This value is the number of additional buffers in the ring that
+	 * describe the buffer space to be consumed for the this packet. If the
+	 * value is zero, then the packet must fit within the space described by
+	 * this BD. If this value is 1 or more, it indicates how many additional
+	 * "buffer" BDs are in the ring immediately following this BD to be used
+	 * for the same network packet. Even if the packet to be placed does not
+	 * need all the additional buffers, they will be consumed anyway.
+	 */
+	#define RX_PROD_PKT_BD_FLAGS_BUFFERS_MASK	UINT32_C(0x300)
+	#define RX_PROD_PKT_BD_FLAGS_BUFFERS_SFT	8
+	#define RX_PROD_PKT_BD_FLAGS_MASK		UINT32_C(0xffc0)
+	#define RX_PROD_PKT_BD_FLAGS_SFT		6
+	uint16_t flags_type;
+
+	/*
+	 * This is the length in Bytes of the host physical buffer where data
+	 * for the packet may be placed in host memory.
+	 */
+	/*
+	 * While this is a Byte resolution value, it is often advantageous to
+	 * ensure that the buffers provided end on a host cache line.
+	 */
+	uint16_t len;
+
+	/*
+	 * The opaque data field is pass through to the completion and can be
+	 * used for any data that the driver wants to associate with this
+	 * receive buffer set.
+	 */
+	uint32_t opaque;
+
+	/*
+	 * This is the host physical address where data for the packet may by
+	 * placed in host memory.
+	 */
+	/*
+	 * While this is a Byte resolution value, it is often advantageous to
+	 * ensure that the buffers provide start on a host cache line.
+	 */
+	uint64_t addr;
+} __attribute__((packed));
+
 /* Completion Ring Structures */
 /* Note: This structure is used by the HWRM to communicate HWRM Error. */
 /* Base Completion Record (16 bytes) */
@@ -611,6 +684,407 @@ struct tx_cmpl {
 	uint32_t unused_2;
 } __attribute__((packed)) tx_cmpl_t, *ptx_cmpl_t;
 
+/* RX Packet Completion Record (32 bytes split to 2 16-byte struct) */
+struct rx_pkt_cmpl {
+	/*
+	 * This field indicates the exact type of the completion. By convention,
+	 * the LSB identifies the length of the record in 16B units. Even values
+	 * indicate 16B records. Odd values indicate 32B records.
+	 */
+	#define RX_PKT_CMPL_TYPE_MASK			UINT32_C(0x3f)
+	#define RX_PKT_CMPL_TYPE_SFT			0
+		/*
+		 * RX L2 completion: Completion of and L2 RX packet.
+		 * Length = 32B
+		 */
+	#define RX_PKT_CMPL_TYPE_RX_L2			(UINT32_C(0x11) << 0)
+	/*
+	 * When this bit is '1', it indicates a packet that has an error of some
+	 * type. Type of error is indicated in error_flags.
+	 */
+	#define RX_PKT_CMPL_FLAGS_ERROR			UINT32_C(0x40)
+	/* This field indicates how the packet was placed in the buffer. */
+	#define RX_PKT_CMPL_FLAGS_PLACEMENT_MASK	UINT32_C(0x380)
+	#define RX_PKT_CMPL_FLAGS_PLACEMENT_SFT		7
+		/* Normal: Packet was placed using normal algorithm. */
+	#define RX_PKT_CMPL_FLAGS_PLACEMENT_NORMAL	(UINT32_C(0x0) << 7)
+		/* Jumbo: Packet was placed using jumbo algorithm. */
+	#define RX_PKT_CMPL_FLAGS_PLACEMENT_JUMBO	(UINT32_C(0x1) << 7)
+		/*
+		 * Header/Data Separation: Packet was placed using Header/Data
+		 * separation algorithm. The separation location is indicated by
+		 * the itype field.
+		 */
+	#define RX_PKT_CMPL_FLAGS_PLACEMENT_HDS		(UINT32_C(0x2) << 7)
+	#define RX_PKT_CMPL_FLAGS_PLACEMENT_LAST \
+						RX_PKT_CMPL_FLAGS_PLACEMENT_HDS
+	/* This bit is '1' if the RSS field in this completion is valid. */
+	#define RX_PKT_CMPL_FLAGS_RSS_VALID		UINT32_C(0x400)
+	/*
+	 * This value indicates what the inner packet determined for the packet
+	 * was.
+	 */
+	#define RX_PKT_CMPL_FLAGS_ITYPE_MASK		UINT32_C(0xf000)
+	#define RX_PKT_CMPL_FLAGS_ITYPE_SFT		12
+		/* Not Known: Indicates that the packet type was not known. */
+	#define RX_PKT_CMPL_FLAGS_ITYPE_NOT_KNOWN	(UINT32_C(0x0) << 12)
+		/*
+		 * IP Packet: Indicates that the packet was an IP packet, but
+		 * further classification was not possible.
+		 */
+	#define RX_PKT_CMPL_FLAGS_ITYPE_IP		(UINT32_C(0x1) << 12)
+		/*
+		 * TCP Packet: Indicates that the packet was IP and TCP. This
+		 * indicates that the payload_offset field is valid.
+		 */
+	#define RX_PKT_CMPL_FLAGS_ITYPE_TCP		(UINT32_C(0x2) << 12)
+		/*
+		 * UDP Packet: Indicates that the packet was IP and UDP. This
+		 * indicates that the payload_offset field is valid.
+		 */
+	#define RX_PKT_CMPL_FLAGS_ITYPE_UDP		(UINT32_C(0x3) << 12)
+		/*
+		 * FCoE Packet: Indicates that the packet was recognized as a
+		 * FCoE. This also indicates that the payload_offset field is
+		 * valid.
+		 */
+	#define RX_PKT_CMPL_FLAGS_ITYPE_FCOE		(UINT32_C(0x4) << 12)
+		/*
+		 * RoCE Packet: Indicates that the packet was recognized as a
+		 * RoCE. This also indicates that the payload_offset field is
+		 * valid.
+		 */
+	#define RX_PKT_CMPL_FLAGS_ITYPE_ROCE		(UINT32_C(0x5) << 12)
+		/*
+		 * ICMP Packet: Indicates that the packet was recognized as
+		 * ICMP. This indicates that the payload_offset field is valid.
+		 */
+	#define RX_PKT_CMPL_FLAGS_ITYPE_ICMP		(UINT32_C(0x7) << 12)
+		/*
+		 * PtP packet wo/timestamp: Indicates that the packet was
+		 * recognized as a PtP packet.
+		 */
+	#define RX_PKT_CMPL_FLAGS_ITYPE_PTP_WO_TIMESTAMP \
+							(UINT32_C(0x8) << 12)
+		/*
+		 * PtP packet w/timestamp: Indicates that the packet was
+		 * recognized as a PtP packet and that a timestamp was taken for
+		 * the packet.
+		 */
+	#define RX_PKT_CMPL_FLAGS_ITYPE_PTP_W_TIMESTAMP	(UINT32_C(0x9) << 12)
+	#define RX_PKT_CMPL_FLAGS_ITYPE_LAST \
+					RX_PKT_CMPL_FLAGS_ITYPE_PTP_W_TIMESTAMP
+	#define RX_PKT_CMPL_FLAGS_MASK			UINT32_C(0xffc0)
+	#define RX_PKT_CMPL_FLAGS_SFT			6
+	uint16_t flags_type;
+
+	/*
+	 * This is the length of the data for the packet stored in the buffer(s)
+	 * identified by the opaque value. This includes the packet BD and any
+	 * associated buffer BDs. This does not include the the length of any
+	 * data places in aggregation BDs.
+	 */
+	uint16_t len;
+
+	/*
+	 * This is a copy of the opaque field from the RX BD this completion
+	 * corresponds to.
+	 */
+	uint32_t opaque;
+
+	/*
+	 * This value is written by the NIC such that it will be different for
+	 * each pass through the completion queue. The even passes will write 1.
+	 * The odd passes will write 0.
+	 */
+	#define RX_PKT_CMPL_V1				UINT32_C(0x1)
+	/*
+	 * This value is the number of aggregation buffers that follow this
+	 * entry in the completion ring that are a part of this packet. If the
+	 * value is zero, then the packet is completely contained in the buffer
+	 * space provided for the packet in the RX ring.
+	 */
+	#define RX_PKT_CMPL_AGG_BUFS_MASK		UINT32_C(0x3e)
+	#define RX_PKT_CMPL_AGG_BUFS_SFT		1
+	uint8_t agg_bufs_v1;
+
+	/*
+	 * This is the RSS hash type for the packet. The value is packed
+	 * {tuple_extrac_op[1:0],rss_profile_id[4:0],tuple_extrac_op[2]}.
+	 */
+	uint8_t rss_hash_type;
+
+	/*
+	 * This value indicates the offset from the beginning of the packet
+	 * where the inner payload starts. This value is valid for TCP, UDP,
+	 * FCoE, and RoCE packets.
+	 */
+	uint8_t payload_offset;
+
+	uint8_t unused_1;
+
+	/*
+	 * This value is the RSS hash value calculated for the packet based on
+	 * the mode bits and key value in the VNIC.
+	 */
+	uint32_t rss_hash;
+} __attribute__((packed));
+
+/* last 16 bytes of RX Packet Completion Record */
+struct rx_pkt_cmpl_hi {
+	/*
+	 * This indicates that the ip checksum was calculated for the inner
+	 * packet and that the ip_cs_error field indicates if there was an
+	 * error.
+	 */
+	#define RX_PKT_CMPL_FLAGS2_IP_CS_CALC		UINT32_C(0x1)
+	/*
+	 * This indicates that the TCP, UDP or ICMP checksum was calculated for
+	 * the inner packet and that the l4_cs_error field indicates if there
+	 * was an error.
+	 */
+	#define RX_PKT_CMPL_FLAGS2_L4_CS_CALC		UINT32_C(0x2)
+	/*
+	 * This indicates that the ip checksum was calculated for the tunnel
+	 * header and that the t_ip_cs_error field indicates if there was an
+	 * error.
+	 */
+	#define RX_PKT_CMPL_FLAGS2_T_IP_CS_CALC		UINT32_C(0x4)
+	/*
+	 * This indicates that the UDP checksum was calculated for the tunnel
+	 * packet and that the t_l4_cs_error field indicates if there was an
+	 * error.
+	 */
+	#define RX_PKT_CMPL_FLAGS2_T_L4_CS_CALC		UINT32_C(0x8)
+	/* This value indicates what format the metadata field is. */
+	#define RX_PKT_CMPL_FLAGS2_META_FORMAT_MASK	UINT32_C(0xf0)
+	#define RX_PKT_CMPL_FLAGS2_META_FORMAT_SFT	4
+		/* No metadata informtaion. Value is zero. */
+	#define RX_PKT_CMPL_FLAGS2_META_FORMAT_NONE	(UINT32_C(0x0) << 4)
+		/*
+		 * The metadata field contains the VLAN tag and TPID value. -
+		 * metadata[11:0] contains the vlan VID value. - metadata[12]
+		 * contains the vlan DE value. - metadata[15:13] contains the
+		 * vlan PRI value. - metadata[31:16] contains the vlan TPID
+		 * value.
+		 */
+	#define RX_PKT_CMPL_FLAGS2_META_FORMAT_VLAN	(UINT32_C(0x1) << 4)
+	#define RX_PKT_CMPL_FLAGS2_META_FORMAT_LAST \
+					RX_PKT_CMPL_FLAGS2_META_FORMAT_VLAN
+	/*
+	 * This field indicates the IP type for the inner-most IP header. A
+	 * value of '0' indicates IPv4. A value of '1' indicates IPv6. This
+	 * value is only valid if itype indicates a packet with an IP header.
+	 */
+	#define RX_PKT_CMPL_FLAGS2_IP_TYPE		UINT32_C(0x100)
+	uint32_t flags2;
+
+	/*
+	 * This is data from the CFA block as indicated by the meta_format
+	 * field.
+	 */
+	/* When meta_format=1, this value is the VLAN VID. */
+	#define RX_PKT_CMPL_METADATA_VID_MASK		UINT32_C(0xfff)
+	#define RX_PKT_CMPL_METADATA_VID_SFT		0
+	/* When meta_format=1, this value is the VLAN DE. */
+	#define RX_PKT_CMPL_METADATA_DE			UINT32_C(0x1000)
+	/* When meta_format=1, this value is the VLAN PRI. */
+	#define RX_PKT_CMPL_METADATA_PRI_MASK		UINT32_C(0xe000)
+	#define RX_PKT_CMPL_METADATA_PRI_SFT		13
+	/* When meta_format=1, this value is the VLAN TPID. */
+	#define RX_PKT_CMPL_METADATA_TPID_MASK		UINT32_C(0xffff0000)
+	#define RX_PKT_CMPL_METADATA_TPID_SFT		16
+	uint32_t metadata;
+
+	/*
+	 * This value is written by the NIC such that it will be different for
+	 * each pass through the completion queue. The even passes will write 1.
+	 * The odd passes will write 0.
+	 */
+	#define RX_PKT_CMPL_V2				UINT32_C(0x1)
+	/*
+	 * This error indicates that there was some sort of problem with the BDs
+	 * for the packet that was found after part of the packet was already
+	 * placed. The packet should be treated as invalid.
+	 */
+	#define RX_PKT_CMPL_ERRORS_BUFFER_ERROR_MASK	UINT32_C(0xe)
+	#define RX_PKT_CMPL_ERRORS_BUFFER_ERROR_SFT	1
+		/* No buffer error */
+	#define RX_PKT_CMPL_ERRORS_BUFFER_ERROR_NO_BUFFER \
+							(UINT32_C(0x0) << 1)
+		/*
+		 * Did Not Fit: Packet did not fit into packet buffer provided.
+		 * For regular placement, this means the packet did not fit in
+		 * the buffer provided. For HDS and jumbo placement, this means
+		 * that the packet could not be placed into 7 physical buffers
+		 * or less.
+		 */
+	#define RX_PKT_CMPL_ERRORS_BUFFER_ERROR_DID_NOT_FIT \
+							(UINT32_C(0x1) << 1)
+		/*
+		 * Not On Chip: All BDs needed for the packet were not on-chip
+		 * when the packet arrived.
+		 */
+	#define RX_PKT_CMPL_ERRORS_BUFFER_ERROR_NOT_ON_CHIP \
+							(UINT32_C(0x2) << 1)
+		/* Bad Format: BDs were not formatted correctly. */
+	#define RX_PKT_CMPL_ERRORS_BUFFER_ERROR_BAD_FORMAT \
+							(UINT32_C(0x3) << 1)
+	#define RX_PKT_CMPL_ERRORS_BUFFER_ERROR_LAST \
+				RX_PKT_CMPL_ERRORS_BUFFER_ERROR_BAD_FORMAT
+	/* This indicates that there was an error in the IP header checksum. */
+	#define RX_PKT_CMPL_ERRORS_IP_CS_ERROR		UINT32_C(0x10)
+	/*
+	 * This indicates that there was an error in the TCP, UDP or ICMP
+	 * checksum.
+	 */
+	#define RX_PKT_CMPL_ERRORS_L4_CS_ERROR		UINT32_C(0x20)
+	/*
+	 * This indicates that there was an error in the tunnel IP header
+	 * checksum.
+	 */
+	#define RX_PKT_CMPL_ERRORS_T_IP_CS_ERROR	UINT32_C(0x40)
+	/* This indicates that there was an error in the tunnel UDP checksum. */
+	#define RX_PKT_CMPL_ERRORS_T_L4_CS_ERROR	UINT32_C(0x80)
+	/*
+	 * This indicates that there was a CRC error on either an FCoE or RoCE
+	 * packet. The itype indicates the packet type.
+	 */
+	#define RX_PKT_CMPL_ERRORS_CRC_ERROR		UINT32_C(0x100)
+	/*
+	 * This indicates that there was an error in the tunnel portion of the
+	 * packet when this field is non-zero.
+	 */
+	#define RX_PKT_CMPL_ERRORS_T_PKT_ERROR_MASK	UINT32_C(0xe00)
+	#define RX_PKT_CMPL_ERRORS_T_PKT_ERROR_SFT	9
+		/*
+		 * No additional error occurred on the tunnel portion of the
+		 * packet of the packet does not have a tunnel.
+		 */
+	#define RX_PKT_CMPL_ERRORS_T_PKT_ERROR_NO_ERROR	(UINT32_C(0x0) << 9)
+		/*
+		 * Indicates that IP header version does not match expectation
+		 * from L2 Ethertype for IPv4 and IPv6 in the tunnel header.
+		 */
+	#define RX_PKT_CMPL_ERRORS_T_PKT_ERROR_T_L3_BAD_VERSION \
+							(UINT32_C(0x1) << 9)
+		/*
+		 * Indicates that header length is out of range in the tunnel
+		 * header. Valid for IPv4.
+		 */
+	#define RX_PKT_CMPL_ERRORS_T_PKT_ERROR_T_L3_BAD_HDR_LEN \
+							(UINT32_C(0x2) << 9)
+		/*
+		 * Indicates that the physical packet is shorter than that
+		 * claimed by the PPPoE header length for a tunnel PPPoE packet.
+		 */
+	#define RX_PKT_CMPL_ERRORS_T_PKT_ERROR_TUNNEL_TOTAL_ERROR \
+							(UINT32_C(0x3) << 9)
+		/*
+		 * Indicates that physical packet is shorter than that claimed
+		 * by the tunnel l3 header length. Valid for IPv4, or IPv6
+		 * tunnel packet packets.
+		 */
+	#define RX_PKT_CMPL_ERRORS_T_PKT_ERROR_T_IP_TOTAL_ERROR \
+							(UINT32_C(0x4) << 9)
+		/*
+		 * Indicates that the physical packet is shorter than that
+		 * claimed by the tunnel UDP header length for a tunnel UDP
+		 * packet that is not fragmented.
+		 */
+	#define RX_PKT_CMPL_ERRORS_T_PKT_ERROR_T_UDP_TOTAL_ERROR \
+							(UINT32_C(0x5) << 9)
+		/*
+		 * indicates that the IPv4 TTL or IPv6 hop limit check have
+		 * failed (e.g. TTL = 0) in the tunnel header. Valid for IPv4,
+		 * and IPv6.
+		 */
+	#define RX_PKT_CMPL_ERRORS_T_PKT_ERROR_T_L3_BAD_TTL \
+							(UINT32_C(0x6) << 9)
+	#define RX_PKT_CMPL_ERRORS_T_PKT_ERROR_LAST \
+				RX_PKT_CMPL_ERRORS_T_PKT_ERROR_T_L3_BAD_TTL
+	/*
+	 * This indicates that there was an error in the inner portion of the
+	 * packet when this field is non-zero.
+	 */
+	#define RX_PKT_CMPL_ERRORS_PKT_ERROR_MASK	UINT32_C(0xf000)
+	#define RX_PKT_CMPL_ERRORS_PKT_ERROR_SFT	12
+		/*
+		 * No additional error occurred on the tunnel portion of the
+		 * packet of the packet does not have a tunnel.
+		 */
+	#define RX_PKT_CMPL_ERRORS_PKT_ERROR_NO_ERROR	(UINT32_C(0x0) << 12)
+		/*
+		 * Indicates that IP header version does not match expectation
+		 * from L2 Ethertype for IPv4 and IPv6 or that option other than
+		 * VFT was parsed on FCoE packet.
+		 */
+	#define RX_PKT_CMPL_ERRORS_PKT_ERROR_L3_BAD_VERSION \
+							(UINT32_C(0x1) << 12)
+		/*
+		 * indicates that header length is out of range. Valid for IPv4
+		 * and RoCE
+		 */
+	#define RX_PKT_CMPL_ERRORS_PKT_ERROR_L3_BAD_HDR_LEN \
+							(UINT32_C(0x2) << 12)
+		/*
+		 * indicates that the IPv4 TTL or IPv6 hop limit check have
+		 * failed (e.g. TTL = 0). Valid for IPv4, and IPv6
+		 */
+	#define RX_PKT_CMPL_ERRORS_PKT_ERROR_L3_BAD_TTL	(UINT32_C(0x3) << 12)
+		/*
+		 * Indicates that physical packet is shorter than that claimed
+		 * by the l3 header length. Valid for IPv4, IPv6 packet or RoCE
+		 * packets.
+		 */
+	#define RX_PKT_CMPL_ERRORS_PKT_ERROR_IP_TOTAL_ERROR \
+							(UINT32_C(0x4) << 12)
+		/*
+		 * Indicates that the physical packet is shorter than that
+		 * claimed by the UDP header length for a UDP packet that is not
+		 * fragmented.
+		 */
+	#define RX_PKT_CMPL_ERRORS_PKT_ERROR_UDP_TOTAL_ERROR \
+							(UINT32_C(0x5) << 12)
+		/*
+		 * Indicates that TCP header length > IP payload. Valid for TCP
+		 * packets only.
+		 */
+	#define RX_PKT_CMPL_ERRORS_PKT_ERROR_L4_BAD_HDR_LEN \
+							(UINT32_C(0x6) << 12)
+		/* Indicates that TCP header length < 5. Valid for TCP. */
+	#define RX_PKT_CMPL_ERRORS_PKT_ERROR_L4_BAD_HDR_LEN_TOO_SMALL \
+							(UINT32_C(0x7) << 12)
+		/*
+		 * Indicates that TCP option headers result in a TCP header size
+		 * that does not match data offset in TCP header. Valid for TCP.
+		 */
+	#define RX_PKT_CMPL_ERRORS_PKT_ERROR_L4_BAD_OPT_LEN \
+							(UINT32_C(0x8) << 12)
+	#define RX_PKT_CMPL_ERRORS_PKT_ERROR_LAST \
+				RX_PKT_CMPL_ERRORS_PKT_ERROR_L4_BAD_OPT_LEN
+	#define RX_PKT_CMPL_ERRORS_MASK			UINT32_C(0xfffe)
+	#define RX_PKT_CMPL_ERRORS_SFT			1
+	uint16_t errors_v2;
+
+	/*
+	 * This field identifies the CFA action rule that was used for this
+	 * packet.
+	 */
+	uint16_t cfa_code;
+
+	/*
+	 * This value holds the reordering sequence number for the packet. If
+	 * the reordering sequence is not valid, then this value is zero. The
+	 * reordering domain for the packet is in the bottom 8 to 10b of the
+	 * rss_hash value. The bottom 20b of this value contain the ordering
+	 * domain value for the packet.
+	 */
+	#define RX_PKT_CMPL_REORDER_MASK		UINT32_C(0xffffff)
+	#define RX_PKT_CMPL_REORDER_SFT			0
+	uint32_t reorder;
+} __attribute__((packed));
+
 /* HWRM Forwarded Request (16 bytes) */
 struct hwrm_fwd_req_cmpl {
 	/* Length of forwarded request in bytes. */
-- 
1.9.1



More information about the dev mailing list