VPP-96 ENID driver update for rx of jumbo pkts using muliple mbuf's

Change-Id: I0e985b079da3224f4886e3ee2cece4d046e291eb
Signed-off-by: John Lo <loj@cisco.com>
diff --git a/dpdk/dpdk-16.04_patches/0015-enic-counter_improvement.patch b/dpdk/dpdk-16.04_patches/0015-enic-counter_improvement.patch
new file mode 100755
index 0000000..6c8986b
--- /dev/null
+++ b/dpdk/dpdk-16.04_patches/0015-enic-counter_improvement.patch
@@ -0,0 +1,148 @@
+diff -ur dpdk-16.04.orig/drivers/net/enic/enic.h dpdk-16.04/drivers/net/enic/enic.h
+--- dpdk-16.04.orig/drivers/net/enic/enic.h	2016-05-26 16:59:16.531326660 -0700
++++ dpdk-16.04/drivers/net/enic/enic.h	2016-05-26 16:59:52.689262489 -0700
+@@ -91,6 +91,11 @@
+ 	struct enic_fdir_node *nodes[ENICPMD_FDIR_MAX];
+ };
+ 
++struct enic_soft_stats {
++	rte_atomic64_t rx_nombuf;
++	rte_atomic64_t rx_packet_errors;
++};
++
+ /* Per-instance private data structure */
+ struct enic {
+ 	struct enic *next;
+@@ -133,6 +138,8 @@
+ 	/* interrupt resource */
+ 	struct vnic_intr intr;
+ 	unsigned int intr_count;
++
++	struct enic_soft_stats soft_stats;
+ };
+ 
+ static inline unsigned int enic_cq_rq(__rte_unused struct enic *enic, unsigned int rq)
+diff -ur dpdk-16.04.orig/drivers/net/enic/enic_main.c dpdk-16.04/drivers/net/enic/enic_main.c
+--- dpdk-16.04.orig/drivers/net/enic/enic_main.c	2016-05-26 16:59:16.533326822 -0700
++++ dpdk-16.04/drivers/net/enic/enic_main.c	2016-05-26 17:08:11.768801926 -0700
+@@ -142,22 +142,51 @@
+ }
+ 
+ 
++static void enic_clear_soft_stats(struct enic *enic)
++{
++	struct enic_soft_stats *soft_stats = &enic->soft_stats;
++	rte_atomic64_clear(&soft_stats->rx_nombuf);
++	rte_atomic64_clear(&soft_stats->rx_packet_errors);
++}
++
++static void enic_init_soft_stats(struct enic *enic)
++{
++	struct enic_soft_stats *soft_stats = &enic->soft_stats;
++	rte_atomic64_init(&soft_stats->rx_nombuf);
++	rte_atomic64_init(&soft_stats->rx_packet_errors);
++	enic_clear_soft_stats(enic);
++}
++
+ void enic_dev_stats_clear(struct enic *enic)
+ {
+ 	if (vnic_dev_stats_clear(enic->vdev))
+ 		dev_err(enic, "Error in clearing stats\n");
++	enic_clear_soft_stats(enic);
+ }
+ 
+ void enic_dev_stats_get(struct enic *enic, struct rte_eth_stats *r_stats)
+ {
+ 	struct vnic_stats *stats;
++	struct enic_soft_stats *soft_stats = &enic->soft_stats;
++	int64_t rx_truncated;
++	uint64_t rx_packet_errors;
+ 
+ 	if (vnic_dev_stats_dump(enic->vdev, &stats)) {
+ 		dev_err(enic, "Error in getting stats\n");
+ 		return;
+ 	}
+ 
+-	r_stats->ipackets = stats->rx.rx_frames_ok;
++	/* The number of truncated packets can only be calculated by
++	 * subtracting a hardware counter from error packets received by
++	 * the driver. Note: this causes transient inaccuracies in the
++	 * ipackets count. Also, the length of truncated packets are
++	 * counted in ibytes even though truncated packets are dropped
++	 * which can make ibytes be slightly higher than it should be.
++	 */
++	rx_packet_errors = rte_atomic64_read(&soft_stats->rx_packet_errors);
++	rx_truncated = rx_packet_errors - stats->rx.rx_errors;
++
++	r_stats->ipackets = stats->rx.rx_frames_ok - rx_truncated;
+ 	r_stats->opackets = stats->tx.tx_frames_ok;
+ 
+ 	r_stats->ibytes = stats->rx.rx_bytes_ok;
+@@ -166,10 +195,9 @@
+ 	r_stats->ierrors = stats->rx.rx_errors + stats->rx.rx_drop;
+ 	r_stats->oerrors = stats->tx.tx_errors;
+ 
+-	r_stats->imissed = stats->rx.rx_no_bufs;
++	r_stats->imissed = stats->rx.rx_no_bufs + rx_truncated;
+ 
+-	r_stats->imcasts = stats->rx.rx_multicast_frames_ok;
+-	r_stats->rx_nombuf = stats->rx.rx_no_bufs;
++	r_stats->rx_nombuf = rte_atomic64_read(&soft_stats->rx_nombuf);
+ }
+ 
+ void enic_del_mac_address(struct enic *enic)
+@@ -755,6 +783,8 @@
+ {
+ 	int ret;
+ 
++	enic_init_soft_stats(enic);
++
+ 	ret = enic_set_rss_nic_cfg(enic);
+ 	if (ret) {
+ 		dev_err(enic, "Failed to config nic, aborting.\n");
+diff -ur dpdk-16.04.orig/drivers/net/enic/enic_rxtx.c dpdk-16.04/drivers/net/enic/enic_rxtx.c
+--- dpdk-16.04.orig/drivers/net/enic/enic_rxtx.c	2016-05-26 16:59:16.522325929 -0700
++++ dpdk-16.04/drivers/net/enic/enic_rxtx.c	2016-05-26 16:59:52.694262896 -0700
+@@ -251,6 +251,7 @@
+ 	struct vnic_cq *cq;
+ 	volatile struct cq_desc *cqd_ptr;
+ 	uint8_t color;
++	uint16_t nb_err = 0;
+ 
+ 	cq = &enic->cq[enic_cq_rq(enic, rq->index)];
+ 	rx_id = cq->to_clean;		/* index of cqd, rqd, mbuf_table */
+@@ -278,10 +279,7 @@
+ 		/* allocate a new mbuf */
+ 		nmb = rte_rxmbuf_alloc(rq->mp);
+ 		if (nmb == NULL) {
+-			dev_err(enic, "RX mbuf alloc failed port=%u qid=%u",
+-			enic->port_id, (unsigned)rq->index);
+-			rte_eth_devices[enic->port_id].
+-					data->rx_mbuf_alloc_failed++;
++			rte_atomic64_inc(&enic->soft_stats.rx_nombuf);
+ 			break;
+ 		}
+ 
+@@ -323,9 +321,10 @@
+ 			rxmb->packet_type = enic_cq_rx_flags_to_pkt_type(&cqd);
+ 			enic_cq_rx_to_pkt_flags(&cqd, rxmb);
+ 		} else {
+-			rxmb->pkt_len = 0;
+-			rxmb->packet_type = 0;
+-			rxmb->ol_flags = 0;
++			rte_pktmbuf_free(rxmb);
++			rte_atomic64_inc(&enic->soft_stats.rx_packet_errors);
++			nb_err++;
++			continue;
+ 		}
+ 		rxmb->data_len = rxmb->pkt_len;
+ 
+@@ -337,7 +336,7 @@
+ 		rx_pkts[nb_rx++] = rxmb;
+ 	}
+ 
+-	nb_hold += nb_rx;
++	nb_hold += nb_rx + nb_err;
+ 	cq->to_clean = rx_id;
+ 
+ 	if (nb_hold > rq->rx_free_thresh) {