net/enic: count truncated packets
[dpdk.git] / drivers / net / enic / enic_main.c
index e3da51d..e4ccc7d 100644 (file)
 #include "vnic_nic.h"
 #include "enic_vnic_wq.h"
 
-static inline struct rte_mbuf *
-rte_rxmbuf_alloc(struct rte_mempool *mp)
-{
-       struct rte_mbuf *m;
-
-       m = __rte_mbuf_raw_alloc(mp);
-       __rte_mbuf_sanity_check_raw(m, 0);
-       return m;
-}
-
-
 static inline int enic_is_sriov_vf(struct enic *enic)
 {
        return enic->pdev->id.device_id == PCI_DEVICE_ID_CISCO_VIC_ENET_VF;
@@ -222,34 +211,62 @@ void enic_send_pkt(struct enic *enic, struct vnic_wq *wq,
                          0 /*wrid*/);
 }
 
+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;
        r_stats->obytes = stats->tx.tx_bytes_ok;
 
-       r_stats->ierrors = stats->rx.rx_errors;
+       r_stats->ierrors = stats->rx.rx_errors + stats->rx.rx_drop;
        r_stats->oerrors = stats->tx.tx_errors;
 
-       r_stats->imissed = stats->rx.rx_drop;
+       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)
@@ -348,17 +365,18 @@ enic_alloc_rx_queue_mbufs(struct enic *enic, struct vnic_rq *rq)
                  rq->ring.desc_count);
 
        for (i = 0; i < rq->ring.desc_count; i++, rqd++) {
-               mb = rte_rxmbuf_alloc(rq->mp);
+               mb = rte_mbuf_raw_alloc(rq->mp);
                if (mb == NULL) {
                        dev_err(enic, "RX mbuf alloc failed queue_id=%u\n",
                        (unsigned)rq->index);
                        return -ENOMEM;
                }
 
-               dma_addr = (dma_addr_t)(mb->buf_physaddr + mb->data_off);
+               dma_addr = (dma_addr_t)(mb->buf_physaddr
+                          + RTE_PKTMBUF_HEADROOM);
 
                rq_enet_desc_enc(rqd, dma_addr, RQ_ENET_TYPE_ONLY_SOP,
-                                mb->buf_len);
+                                mb->buf_len - RTE_PKTMBUF_HEADROOM);
                rq->mbuf_ring[i] = mb;
        }
 
@@ -806,6 +824,8 @@ int enic_setup_finish(struct enic *enic)
 {
        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");