net/ipn3ke: implement statistics
authorAndy Pei <andy.pei@intel.com>
Mon, 1 Jul 2019 10:36:28 +0000 (18:36 +0800)
committerFerruh Yigit <ferruh.yigit@intel.com>
Mon, 8 Jul 2019 19:26:52 +0000 (21:26 +0200)
This patch implements statistics read and reset function for ipn3ke.

Signed-off-by: Andy Pei <andy.pei@intel.com>
Acked-by: Rosen Xu <rosen.xu@intel.com>
drivers/net/ipn3ke/ipn3ke_representor.c

index 4456d9d..8300cc3 100644 (file)
@@ -3,6 +3,7 @@
  */
 
 #include <stdint.h>
+#include <unistd.h>
 
 #include <rte_bus_pci.h>
 #include <rte_ethdev.h>
@@ -297,31 +298,2080 @@ ipn3ke_rpst_tx_queue_release(__rte_unused void *txq)
 {
 }
 
+/* Statistics collected by each port, VSI, VEB, and S-channel */
+struct ipn3ke_rpst_eth_stats {
+       uint64_t tx_bytes;               /* gotc */
+       uint64_t tx_multicast;           /* mptc */
+       uint64_t tx_broadcast;           /* bptc */
+       uint64_t tx_unicast;             /* uptc */
+       uint64_t tx_discards;            /* tdpc */
+       uint64_t tx_errors;              /* tepc */
+       uint64_t rx_bytes;               /* gorc */
+       uint64_t rx_multicast;           /* mprc */
+       uint64_t rx_broadcast;           /* bprc */
+       uint64_t rx_unicast;             /* uprc */
+       uint64_t rx_discards;            /* rdpc */
+       uint64_t rx_unknown_protocol;    /* rupp */
+};
+
+/* store statistics names and its offset in stats structure */
+struct ipn3ke_rpst_xstats_name_offset {
+       char name[RTE_ETH_XSTATS_NAME_SIZE];
+       unsigned int offset;
+};
+
+static const struct ipn3ke_rpst_xstats_name_offset
+ipn3ke_rpst_stats_strings[] = {
+       {"tx_multicast_packets",          offsetof(struct ipn3ke_rpst_eth_stats,
+                                                       tx_multicast)},
+       {"tx_broadcast_packets",          offsetof(struct ipn3ke_rpst_eth_stats,
+                                                       tx_broadcast)},
+       {"tx_unicast_packets",            offsetof(struct ipn3ke_rpst_eth_stats,
+                                                       tx_unicast)},
+       {"tx_dropped_packets",            offsetof(struct ipn3ke_rpst_eth_stats,
+                                                       tx_discards)},
+       {"rx_multicast_packets",          offsetof(struct ipn3ke_rpst_eth_stats,
+                                                       rx_multicast)},
+       {"rx_broadcast_packets",          offsetof(struct ipn3ke_rpst_eth_stats,
+                                                       rx_broadcast)},
+       {"rx_unicast_packets",            offsetof(struct ipn3ke_rpst_eth_stats,
+                                                       rx_unicast)},
+       {"rx_dropped_packets",            offsetof(struct ipn3ke_rpst_eth_stats,
+                                                       rx_discards)},
+       {"rx_unknown_protocol_packets", offsetof(struct ipn3ke_rpst_eth_stats,
+                                                       rx_unknown_protocol)},
+};
+
+#define IPN3KE_RPST_ETH_XSTATS_CNT (sizeof(ipn3ke_rpst_stats_strings) / \
+               sizeof(ipn3ke_rpst_stats_strings[0]))
+
+#define IPN3KE_RPST_PRIO_XSTATS_CNT    8
+
+/* Statistics collected by the MAC */
+struct ipn3ke_rpst_hw_port_stats {
+       /* eth stats collected by the port */
+       struct ipn3ke_rpst_eth_stats eth;
+
+       /* additional port specific stats */
+       uint64_t tx_dropped_link_down;
+       uint64_t crc_errors;
+       uint64_t illegal_bytes;
+       uint64_t error_bytes;
+       uint64_t mac_local_faults;
+       uint64_t mac_remote_faults;
+       uint64_t rx_length_errors;
+       uint64_t link_xon_rx;
+       uint64_t link_xoff_rx;
+       uint64_t priority_xon_rx[IPN3KE_RPST_PRIO_XSTATS_CNT];
+       uint64_t priority_xoff_rx[IPN3KE_RPST_PRIO_XSTATS_CNT];
+       uint64_t link_xon_tx;
+       uint64_t link_xoff_tx;
+       uint64_t priority_xon_tx[IPN3KE_RPST_PRIO_XSTATS_CNT];
+       uint64_t priority_xoff_tx[IPN3KE_RPST_PRIO_XSTATS_CNT];
+       uint64_t priority_xon_2_xoff[IPN3KE_RPST_PRIO_XSTATS_CNT];
+       uint64_t rx_size_64;
+       uint64_t rx_size_65_127;
+       uint64_t rx_size_128_255;
+       uint64_t rx_size_256_511;
+       uint64_t rx_size_512_1023;
+       uint64_t rx_size_1024_1518;
+       uint64_t rx_size_big;
+       uint64_t rx_undersize;
+       uint64_t rx_fragments;
+       uint64_t rx_oversize;
+       uint64_t rx_jabber;
+       uint64_t tx_size_64;
+       uint64_t tx_size_65_127;
+       uint64_t tx_size_128_255;
+       uint64_t tx_size_256_511;
+       uint64_t tx_size_512_1023;
+       uint64_t tx_size_1024_1518;
+       uint64_t tx_size_1519_to_max;
+       uint64_t mac_short_packet_dropped;
+       uint64_t checksum_error;
+       /* flow director stats */
+       uint64_t fd_atr_match;
+       uint64_t fd_sb_match;
+       uint64_t fd_atr_tunnel_match;
+       uint32_t fd_atr_status;
+       uint32_t fd_sb_status;
+       /* EEE LPI */
+       uint32_t tx_lpi_status;
+       uint32_t rx_lpi_status;
+       uint64_t tx_lpi_count;
+       uint64_t rx_lpi_count;
+};
+
+static const struct ipn3ke_rpst_xstats_name_offset
+ipn3ke_rpst_hw_port_strings[] = {
+       {"tx_link_down_dropped",      offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                               tx_dropped_link_down)},
+       {"rx_crc_errors",             offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                               crc_errors)},
+       {"rx_illegal_byte_errors",    offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                               illegal_bytes)},
+       {"rx_error_bytes",            offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                               error_bytes)},
+       {"mac_local_errors",          offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                               mac_local_faults)},
+       {"mac_remote_errors",         offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                               mac_remote_faults)},
+       {"rx_length_errors",          offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                               rx_length_errors)},
+       {"tx_xon_packets",            offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                               link_xon_tx)},
+       {"rx_xon_packets",            offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                               link_xon_rx)},
+       {"tx_xoff_packets",           offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                               link_xoff_tx)},
+       {"rx_xoff_packets",           offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                               link_xoff_rx)},
+       {"rx_size_64_packets",        offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                               rx_size_64)},
+       {"rx_size_65_to_127_packets", offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                               rx_size_65_127)},
+       {"rx_size_128_to_255_packets",
+                               offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                        rx_size_128_255)},
+       {"rx_size_256_to_511_packets",
+                               offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                        rx_size_256_511)},
+       {"rx_size_512_to_1023_packets",
+                               offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                        rx_size_512_1023)},
+       {"rx_size_1024_to_1518_packets",
+                               offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                        rx_size_1024_1518)},
+       {"rx_size_1519_to_max_packets",
+                               offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                        rx_size_big)},
+       {"rx_undersized_errors",      offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                              rx_undersize)},
+       {"rx_oversize_errors",        offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                              rx_oversize)},
+       {"rx_mac_short_dropped",      offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                              mac_short_packet_dropped)},
+       {"rx_fragmented_errors",      offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                              rx_fragments)},
+       {"rx_jabber_errors",          offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                              rx_jabber)},
+       {"tx_size_64_packets",        offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                              tx_size_64)},
+       {"tx_size_65_to_127_packets",
+                               offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                        tx_size_65_127)},
+       {"tx_size_128_to_255_packets",
+                               offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                        tx_size_128_255)},
+       {"tx_size_256_to_511_packets",
+                               offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                        tx_size_256_511)},
+       {"tx_size_512_to_1023_packets",
+                               offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                        tx_size_512_1023)},
+       {"tx_size_1024_to_1518_packets",
+                               offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                        tx_size_1024_1518)},
+       {"tx_size_1519_to_max_packets",
+                               offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                        tx_size_1519_to_max)},
+       {"rx_flow_director_atr_match_packets",
+                               offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                        fd_atr_match)},
+       {"rx_flow_director_sb_match_packets",
+                               offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                        fd_sb_match)},
+       {"tx_low_power_idle_status",  offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                              tx_lpi_status)},
+       {"rx_low_power_idle_status",  offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                              rx_lpi_status)},
+       {"tx_low_power_idle_count",   offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                              tx_lpi_count)},
+       {"rx_low_power_idle_count",   offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                              rx_lpi_count)},
+};
+
+#define IPN3KE_RPST_HW_PORT_XSTATS_CNT (sizeof(ipn3ke_rpst_hw_port_strings) \
+               / sizeof(ipn3ke_rpst_hw_port_strings[0]))
+
+static const struct ipn3ke_rpst_xstats_name_offset
+ipn3ke_rpst_rxq_prio_strings[] = {
+       {"xon_packets",               offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                              priority_xon_rx)},
+       {"xoff_packets",              offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                              priority_xoff_rx)},
+};
+
+#define IPN3KE_RPST_RXQ_PRIO_XSTATS_CNT (sizeof(ipn3ke_rpst_rxq_prio_strings) \
+               / sizeof(ipn3ke_rpst_rxq_prio_strings[0]))
+
+static const struct ipn3ke_rpst_xstats_name_offset
+ipn3ke_rpst_txq_prio_strings[] = {
+       {"xon_packets",               offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                              priority_xon_tx)},
+       {"xoff_packets",              offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                              priority_xoff_tx)},
+       {"xon_to_xoff_packets",       offsetof(struct ipn3ke_rpst_hw_port_stats,
+                                              priority_xon_2_xoff)},
+};
+
+#define IPN3KE_RPST_TXQ_PRIO_XSTATS_CNT (sizeof(ipn3ke_rpst_txq_prio_strings) \
+               / sizeof(ipn3ke_rpst_txq_prio_strings[0]))
+
+static uint32_t
+ipn3ke_rpst_xstats_calc_num(void)
+{
+       return IPN3KE_RPST_ETH_XSTATS_CNT
+               + IPN3KE_RPST_HW_PORT_XSTATS_CNT
+               + (IPN3KE_RPST_RXQ_PRIO_XSTATS_CNT
+                       * IPN3KE_RPST_PRIO_XSTATS_CNT)
+               + (IPN3KE_RPST_TXQ_PRIO_XSTATS_CNT
+                       * IPN3KE_RPST_PRIO_XSTATS_CNT);
+}
+
+static void
+ipn3ke_rpst_25g_nic_side_tx_stats_reset(struct ipn3ke_hw *hw,
+uint16_t port_id)
+{
+       uint32_t tmp = 0x00000001;
+       /* Bit[0]: Software can set this bit to the value of 1
+        * to reset all of the TX statistics registers at the same time.
+        * This bit is selfclearing.
+        */
+       (*hw->f_mac_write)(hw,
+                       tmp,
+                       IPN3KE_25G_TX_STATISTICS_CONFIG,
+                       port_id,
+                       1);
+
+       while (tmp & 0x00000001) {
+               tmp = 0x00000000;
+               (*hw->f_mac_read)(hw,
+                               &tmp,
+                               IPN3KE_25G_TX_STATISTICS_CONFIG,
+                               port_id,
+                               1);
+               if (tmp & 0x00000001)
+                       usleep(5);
+               else
+                       return;
+       }
+}
+
+static void
+ipn3ke_rpst_25g_nic_side_rx_stats_reset(struct ipn3ke_hw *hw,
+uint16_t port_id)
+{
+       uint32_t tmp = 0x00000001;
+       /* Bit[0]: Software can set this bit to the value of 1
+        * to reset all of the RX statistics registers at the same time.
+        * This bit is selfclearing.
+        */
+       (*hw->f_mac_write)(hw,
+                       tmp,
+                       IPN3KE_25G_RX_STATISTICS_CONFIG,
+                       port_id,
+                       1);
+
+       while (tmp & 0x00000001) {
+               tmp = 0x00000000;
+               (*hw->f_mac_read)(hw,
+                               &tmp,
+                               IPN3KE_25G_RX_STATISTICS_CONFIG,
+                               port_id,
+                               1);
+               if (tmp & 0x00000001)
+                       usleep(5);
+               else
+                       return;
+       }
+}
+
+static void
+ipn3ke_rpst_10g_nic_side_tx_stats_reset(struct ipn3ke_hw *hw,
+uint16_t port_id)
+{
+       uint32_t tmp;
+
+       /*Bit [0]: Set this register to 1 to clear all TX statistics
+        *counters.
+        *The IP core clears this bit when all counters are cleared.
+        *Bits [31:1]: Reserved.
+        */
+       tmp = 0x00000000;
+       (*hw->f_mac_read)(hw,
+               &tmp,
+               IPN3KE_10G_TX_STATS_CLR,
+               port_id,
+               1);
+       tmp |= 0x00000001;
+       (*hw->f_mac_write)(hw,
+               tmp,
+               IPN3KE_10G_TX_STATS_CLR,
+               port_id,
+               1);
+}
+
+static void
+ipn3ke_rpst_10g_nic_side_rx_stats_reset(struct ipn3ke_hw *hw,
+uint16_t port_id)
+{
+       uint32_t tmp;
+
+       /*Bit [0]: Set this register to 1 to clear all RX statistics
+        *counters.
+        *The IP core clears this bit when all counters are cleared.
+        *Bits [31:1]: Reserved
+        */
+       tmp = 0x00000000;
+       (*hw->f_mac_read)(hw,
+               &tmp,
+               IPN3KE_10G_RX_STATS_CLR,
+               port_id,
+               1);
+       tmp |= 0x00000001;
+       (*hw->f_mac_write)(hw,
+               tmp,
+               IPN3KE_10G_RX_STATS_CLR,
+               port_id,
+               1);
+}
+
+static uint64_t
+ipn3ke_rpst_read_64bits_statistics_register(uint32_t addr_lo,
+uint32_t addr_hi, struct ipn3ke_hw *hw, uint16_t port_id)
+{
+       uint32_t statistics_lo = 0x00000000;
+       uint32_t statistics_hi = 0x00000000;
+       uint64_t statistics = 0x0000000000000000;
+
+       (*hw->f_mac_read)(hw,
+                       &statistics_lo,
+                       addr_lo,
+                       port_id,
+                       0);
+
+       (*hw->f_mac_read)(hw,
+                       &statistics_hi,
+                       addr_hi,
+                       port_id,
+                       0);
+
+       statistics += statistics_hi;
+       statistics = statistics << IPN3KE_REGISTER_WIDTH;
+       statistics += statistics_lo;
+       return statistics;
+
+}
+
 static int
-ipn3ke_rpst_stats_get(__rte_unused struct rte_eth_dev *ethdev,
-       __rte_unused struct rte_eth_stats *stats)
+ipn3ke_rpst_read_25g_lineside_stats_registers
+(struct ipn3ke_hw *hw,
+uint16_t port_id,
+struct ipn3ke_rpst_hw_port_stats *hw_stats)
 {
+       uint32_t tmp;
+       uint64_t statistics;
+
+       memset(hw_stats, 0, sizeof(*hw_stats));
+
+       /*check Tx statistics is real time.
+        *if statistics has been paused, make it real time.
+        */
+       tmp = 0x00000000;
+       (*hw->f_mac_read)(hw,
+                       &tmp,
+                       IPN3KE_25G_TX_STATISTICS_CONFIG,
+                       port_id,
+                       0);
+
+       if (tmp & IPN3KE_25G_TX_STATISTICS_CONFIG_SHADOW_REQUEST_MASK) {
+               tmp &= 0xfffffffb;
+               (*hw->f_mac_write)(hw,
+                       tmp,
+                       IPN3KE_25G_TX_STATISTICS_CONFIG,
+                       port_id,
+                       0);
+       }
+
+       tmp = 0x00000000;
+       (*hw->f_mac_read)(hw,
+               &tmp,
+               IPN3KE_25G_TX_STATISTICS_STATUS,
+               port_id,
+               1);
+       if (tmp & IPN3KE_25G_TX_STATISTICS_STATUS_SHADOW_REQUEST_MASK) {
+               tmp = 0x00000000;
+               (*hw->f_mac_read)(hw,
+                       &tmp,
+                       IPN3KE_25G_TX_STATISTICS_CONFIG,
+                       port_id,
+                       0);
+               tmp &= 0xfffffffb;
+               (*hw->f_mac_write)(hw,
+                       tmp,
+                       IPN3KE_25G_TX_STATISTICS_CONFIG,
+                       port_id,
+                       0);
+       }
+
+       /*check Rx statistics is real time.
+        *if statistics has been paused, make it real time.
+        */
+       tmp = 0x00000000;
+       (*hw->f_mac_read)(hw,
+                       &tmp,
+                       IPN3KE_25G_RX_STATISTICS_CONFIG,
+                       port_id,
+                       0);
+       if (tmp & IPN3KE_25G_RX_STATISTICS_CONFIG_SHADOW_REQUEST_MASK) {
+               tmp &= 0xfffffffb;
+               (*hw->f_mac_write)(hw,
+                       tmp,
+                       IPN3KE_25G_RX_STATISTICS_CONFIG,
+                       port_id,
+                       0);
+       }
+
+       tmp = 0x00000000;
+       (*hw->f_mac_read)(hw,
+               &tmp,
+               IPN3KE_25G_RX_STATISTICS_STATUS,
+               port_id,
+               0);
+
+       if (tmp & IPN3KE_25G_RX_STATISTICS_STATUS_SHADOW_REQUEST_MASK) {
+               tmp = 0x00000000;
+               (*hw->f_mac_read)(hw,
+                       &tmp,
+                       IPN3KE_25G_RX_STATISTICS_CONFIG,
+                       port_id,
+                       0);
+               tmp &= 0xfffffffb;
+               (*hw->f_mac_write)(hw,
+                       tmp,
+                       IPN3KE_25G_RX_STATISTICS_CONFIG,
+                       port_id,
+                       0);
+       }
+
+       /* pause Tx counter to read the statistics */
+       tmp = 0x00000000;
+       (*hw->f_mac_read)(hw,
+               &tmp,
+               IPN3KE_25G_TX_STATISTICS_CONFIG,
+               port_id,
+               0);
+       tmp |= 0x00000004;
+       (*hw->f_mac_write)(hw,
+               tmp,
+               IPN3KE_25G_TX_STATISTICS_CONFIG,
+               port_id,
+               0);
+
+       /* pause Rx counter to read the statistics */
+       tmp = 0x00000000;
+       (*hw->f_mac_read)(hw,
+               &tmp,
+               IPN3KE_25G_RX_STATISTICS_CONFIG,
+               port_id,
+               0);
+       tmp |= 0x00000004;
+       (*hw->f_mac_write)(hw,
+               tmp,
+               IPN3KE_25G_RX_STATISTICS_CONFIG,
+               port_id,
+               0);
+
+       /*Number of transmitted frames less than 64 bytes
+        *and reporting a CRC error
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_TX_FRAGMENTS_LO,
+               IPN3KE_25G_CNTR_TX_FRAGMENTS_HI,
+               hw, port_id);
+       hw_stats->eth.tx_errors += statistics;
+       hw_stats->crc_errors += statistics;
+
+       /*Number of transmitted oversized frames reporting a CRC error*/
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_TX_JABBERS_LO,
+               IPN3KE_25G_CNTR_TX_JABBERS_HI,
+               hw, port_id);
+       hw_stats->eth.tx_errors += statistics;
+       hw_stats->crc_errors += statistics;
+
+       /* Number of transmitted packets with FCS errors */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_TX_FCS_LO,
+               IPN3KE_25G_CNTR_TX_FCS_HI,
+               hw, port_id);
+       hw_stats->eth.tx_errors += statistics;
+       hw_stats->checksum_error += statistics;
+
+       /*Number of transmitted frames with a frame of length at
+        *least 64 reporting a CRC error
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_TX_CRCERR_LO,
+               IPN3KE_25G_CNTR_TX_CRCERR_HI,
+               hw, port_id);
+       hw_stats->eth.tx_errors += statistics;
+       hw_stats->crc_errors += statistics;
+
+       /*Number of errored multicast frames transmitted,
+        *excluding control frames
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_TX_MCAST_DATA_ERR_LO,
+               IPN3KE_25G_CNTR_TX_MCAST_DATA_ERR_HI,
+               hw, port_id);
+       hw_stats->eth.tx_errors += statistics;
+
+       /*Number of errored broadcast frames transmitted,
+        *excluding control frames
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_TX_BCAST_DATA_ERR_LO,
+               IPN3KE_25G_CNTR_TX_BCAST_DATA_ERR_HI,
+               hw, port_id);
+       hw_stats->eth.tx_errors += statistics;
+
+       /*Number of errored unicast frames transmitted,
+        *excluding control frames
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_TX_UCAST_DATA_ERR_LO,
+               IPN3KE_25G_CNTR_TX_UCAST_DATA_ERR_HI,
+               hw, port_id);
+       hw_stats->eth.tx_errors += statistics;
+
+       /* Number of errored multicast control frames transmitted */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_TX_MCAST_CTRL_ERR_LO,
+               IPN3KE_25G_CNTR_TX_MCAST_CTRL_ERR_HI,
+               hw, port_id);
+       hw_stats->eth.tx_errors += statistics;
+
+       /* Number of errored broadcast control frames transmitted */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_TX_BCAST_CTRL_ERR_LO,
+               IPN3KE_25G_CNTR_TX_BCAST_CTRL_ERR_HI,
+               hw, port_id);
+       hw_stats->eth.tx_errors += statistics;
+
+       /* Number of errored unicast control frames transmitted */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_TX_UCAST_CTRL_ERR_LO,
+               IPN3KE_25G_CNTR_TX_UCAST_CTRL_ERR_HI,
+               hw, port_id);
+       hw_stats->eth.tx_errors += statistics;
+
+       /* Number of errored pause frames transmitted */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_TX_PAUSE_ERR_LO,
+               IPN3KE_25G_CNTR_TX_PAUSE_ERR_HI,
+               hw, port_id);
+       hw_stats->eth.tx_errors += statistics;
+
+       /*Number of 64-byte transmitted frames,
+        *including the CRC field but excluding the preamble
+        *and SFD bytes
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_TX_64B_LO,
+               IPN3KE_25G_CNTR_TX_64B_HI,
+               hw, port_id);
+       hw_stats->tx_size_64 += statistics;
+
+       /* Number of transmitted frames between 65 and 127 bytes */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_TX_65_127B_LO,
+               IPN3KE_25G_CNTR_TX_65_127B_HI,
+               hw, port_id);
+       hw_stats->tx_size_65_127 += statistics;
+
+       /* Number of transmitted frames between 128 and 255 bytes */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_TX_128_255B_LO,
+               IPN3KE_25G_CNTR_TX_128_255B_HI,
+               hw, port_id);
+       hw_stats->tx_size_128_255 += statistics;
+
+       /* Number of transmitted frames between 256 and 511 bytes */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_TX_256_511B_LO,
+               IPN3KE_25G_CNTR_TX_256_511B_HI,
+               hw, port_id);
+       hw_stats->tx_size_256_511 += statistics;
+
+       /* Number of transmitted frames between 512 and 1023 bytes */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_TX_512_1023B_LO,
+               IPN3KE_25G_CNTR_TX_512_1023B_HI,
+               hw, port_id);
+       hw_stats->tx_size_512_1023 += statistics;
+
+       /* Number of transmitted frames between 1024 and 1518 bytes */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_TX_1024_1518B_LO,
+               IPN3KE_25G_CNTR_TX_1024_1518B_HI,
+               hw, port_id);
+       hw_stats->tx_size_1024_1518 += statistics;
+
+       /*Number of transmitted frames of size between 1519 bytes
+        *and the number of bytes specified in the MAX_TX_SIZE_CONFIG
+        *register
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_TX_1519_MAXB_LO,
+               IPN3KE_25G_CNTR_TX_1519_MAXB_HI,
+               hw, port_id);
+       hw_stats->tx_size_1519_to_max += statistics;
+
+       /*Number of oversized frames (frames with more bytes than the
+        *number specified in the MAX_TX_SIZE_CONFIG register)
+        *transmitted
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_TX_OVERSIZE_LO,
+               IPN3KE_25G_CNTR_TX_OVERSIZE_HI,
+               hw, port_id);
+
+       /*Number of valid multicast frames transmitted,
+        *excluding control frames
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_TX_MCAST_DATA_OK_LO,
+               IPN3KE_25G_CNTR_TX_MCAST_DATA_OK_HI,
+               hw, port_id);
+       hw_stats->eth.tx_multicast += statistics;
+
+       /*Number of valid broadcast frames transmitted,
+        *excluding control frames
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_TX_BCAST_DATA_OK_LO,
+               IPN3KE_25G_CNTR_TX_BCAST_DATA_OK_HI,
+               hw, port_id);
+       hw_stats->eth.tx_broadcast += statistics;
+
+       /*Number of valid unicast frames transmitted,
+        *excluding control frames
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_TX_UCAST_DATA_OK_LO,
+               IPN3KE_25G_CNTR_TX_UCAST_DATA_OK_HI,
+               hw, port_id);
+       hw_stats->eth.tx_unicast += statistics;
+
+       /*Number of valid multicast frames transmitted,
+        *excluding data frames
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_TX_MCAST_CTRL_LO,
+               IPN3KE_25G_CNTR_TX_MCAST_CTRL_HI,
+               hw, port_id);
+       hw_stats->eth.tx_multicast += statistics;
+
+       /*Number of valid broadcast frames transmitted,
+        *excluding data frames
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_TX_BCAST_CTRL_LO,
+               IPN3KE_25G_CNTR_TX_BCAST_CTRL_HI,
+               hw, port_id);
+       hw_stats->eth.tx_broadcast += statistics;
+
+       /*Number of valid unicast frames transmitted,
+        *excluding data frames
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_TX_UCAST_CTRL_LO,
+               IPN3KE_25G_CNTR_TX_UCAST_CTRL_HI,
+               hw, port_id);
+       hw_stats->eth.tx_unicast += statistics;
+
+       /* Number of valid pause frames transmitted */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_TX_PAUSE_LO,
+               IPN3KE_25G_CNTR_TX_PAUSE_HI,
+               hw, port_id);
+
+       /*Number of transmitted runt packets. The IP core does not
+        *transmit frames of length less than nine bytes.
+        *The IP core pads frames of length nine bytes to 64 bytes to
+        *extend them to 64 bytes. Therefore, this counter does not
+        *increment in normal operating conditions.
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_TX_RUNT_LO,
+               IPN3KE_25G_CNTR_TX_RUNT_HI,
+               hw, port_id);
+
+       /*Number of transmitted payload bytes in frames with no FCS,
+        *undersized, oversized, or payload length errors.
+        *If VLAN detection is turned off for the TX MAC (bit[1]
+        *of the TX_MAC_CONTROL register at offset 0x40A has
+        *the value of 1), the IP core counts the VLAN header bytes
+        *(4 bytes for VLAN and 8 bytes for stacked VLAN)
+        *as payload bytes. This register is compliant with
+        *the requirements for aOctetsTransmittedOK in section
+        *5.2.2.1.8 of the IEEE Standard 802.3-2008.
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_TX_PAYLOAD_OCTETS_OK_LO,
+               IPN3KE_25G_TX_PAYLOAD_OCTETS_OK_HI,
+               hw, port_id);
+       hw_stats->eth.tx_bytes += statistics;
+
+       /*Number of transmitted bytes in frames with no FCS, undersized,
+        *oversized, or payload length errors. This register is
+        *compliant with the requirements for ifOutOctets in RFC3635
+        *(Managed Objects for Ethernet-like Interface Types)
+        *and TX etherStatsOctets in RFC2819(Remote Network Monitoring
+        *Management Information Base (RMON)).
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_TX_FRAME_OCTETS_OK_LO,
+               IPN3KE_25G_TX_FRAME_OCTETS_OK_HI,
+               hw, port_id);
+
+       /*Number of received frames less than 64 bytes
+        *and reporting a CRC error
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_RX_FRAGMENTS_LO,
+               IPN3KE_25G_CNTR_RX_FRAGMENTS_HI,
+               hw, port_id);
+       hw_stats->eth.rx_discards += statistics;
+       hw_stats->crc_errors += statistics;
+       hw_stats->rx_length_errors += statistics;
+
+       /* Number of received oversized frames reporting a CRC error */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_RX_JABBERS_LO,
+               IPN3KE_25G_CNTR_RX_JABBERS_HI,
+               hw, port_id);
+       hw_stats->eth.rx_discards += statistics;
+       hw_stats->crc_errors += statistics;
+       hw_stats->rx_length_errors += statistics;
+
+       /*Number of received packets with FCS errors.
+        *This register maintains a count of the number of pulses
+        *on the "l<n>_rx_fcs_error" or "rx_fcs_error" output signal
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_RX_FCS_LO,
+               IPN3KE_25G_CNTR_RX_FCS_HI,
+               hw, port_id);
+       hw_stats->eth.rx_discards += statistics;
+       hw_stats->checksum_error += statistics;
+
+       /*Number of received frames with a frame of length at least 64
+        *with CRC error
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_RX_CRCERR_LO,
+               IPN3KE_25G_CNTR_RX_CRCERR_HI,
+               hw, port_id);
+       hw_stats->eth.rx_discards += statistics;
+       hw_stats->crc_errors += statistics;
+
+       /*Number of errored multicast frames received,
+        *excluding control frames
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_RX_MCAST_DATA_ERR_LO,
+               IPN3KE_25G_CNTR_RX_MCAST_DATA_ERR_HI,
+               hw, port_id);
+       hw_stats->eth.rx_discards += statistics;
+
+       /*Number of errored broadcast frames received,
+        *excluding control frames
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_RX_BCAST_DATA_ERR_LO,
+               IPN3KE_25G_CNTR_RX_BCAST_DATA_ERR_HI,
+               hw, port_id);
+       hw_stats->eth.rx_discards += statistics;
+
+       /*Number of errored unicast frames received,
+        *excluding control frames
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_RX_UCAST_DATA_ERR_LO,
+               IPN3KE_25G_CNTR_RX_UCAST_DATA_ERR_HI,
+               hw, port_id);
+       hw_stats->eth.rx_discards += statistics;
+
+       /* Number of errored multicast control frames received */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_RX_MCAST_CTRL_ERR_LO,
+               IPN3KE_25G_CNTR_RX_MCAST_CTRL_ERR_HI,
+               hw, port_id);
+       hw_stats->eth.rx_discards += statistics;
+
+       /* Number of errored broadcast control frames received */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_RX_BCAST_CTRL_ERR_LO,
+               IPN3KE_25G_CNTR_RX_BCAST_CTRL_ERR_HI,
+               hw, port_id);
+       hw_stats->eth.rx_discards += statistics;
+
+       /* Number of errored unicast control frames received */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_RX_UCAST_CTRL_ERR_LO,
+               IPN3KE_25G_CNTR_RX_UCAST_CTRL_ERR_HI,
+               hw, port_id);
+       hw_stats->eth.rx_discards += statistics;
+
+       /* Number of errored pause frames received */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_RX_PAUSE_ERR_LO,
+               IPN3KE_25G_CNTR_RX_PAUSE_ERR_HI,
+               hw, port_id);
+       hw_stats->eth.rx_discards += statistics;
+
+       /*Number of 64-byte received frames,
+        *including the CRC field but excluding the preamble
+        *and SFD bytes
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_RX_64B_LO,
+               IPN3KE_25G_CNTR_RX_64B_HI,
+               hw, port_id);
+       hw_stats->rx_size_64 += statistics;
+
+       /*Number of received frames between 65 and 127 bytes */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_RX_65_127B_LO,
+               IPN3KE_25G_CNTR_RX_65_127B_HI,
+               hw, port_id);
+       hw_stats->rx_size_65_127 += statistics;
+
+       /*Number of received frames between 128 and 255 bytes
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_RX_128_255B_LO,
+               IPN3KE_25G_CNTR_RX_128_255B_HI,
+               hw, port_id);
+       hw_stats->rx_size_128_255 += statistics;
+
+       /*Number of received frames between 256 and 511 bytes
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_RX_256_511B_LO,
+               IPN3KE_25G_CNTR_RX_256_511B_HI,
+               hw, port_id);
+       hw_stats->rx_size_256_511 += statistics;
+
+       /*Number of received frames between 512 and 1023 bytes
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_RX_512_1023B_LO,
+               IPN3KE_25G_CNTR_RX_512_1023B_HI,
+               hw, port_id);
+       hw_stats->rx_size_512_1023 += statistics;
+
+       /*Number of received frames between 1024 and 1518 bytes
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_RX_1024_1518B_LO,
+               IPN3KE_25G_CNTR_RX_1024_1518B_HI,
+               hw, port_id);
+       hw_stats->rx_size_1024_1518 += statistics;
+
+       /*Number of received frames of size between 1519 bytes
+        *and the number of bytes specified in the MAX_TX_SIZE_CONFIG
+        *register
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_RX_1519_MAXB_LO,
+               IPN3KE_25G_CNTR_RX_1519_MAXB_HI,
+               hw, port_id);
+       hw_stats->rx_size_big += statistics;
+
+       /*Number of oversized frames (frames with more bytes
+        *than the number specified in the MAX_TX_SIZE_CONFIG register)
+        *received
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_RX_OVERSIZE_LO,
+               IPN3KE_25G_CNTR_RX_OVERSIZE_HI,
+               hw, port_id);
+       hw_stats->rx_jabber += statistics;
+
+       /*Number of valid multicast frames received,
+        *excluding control frames
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_RX_MCAST_DATA_OK_LO,
+               IPN3KE_25G_CNTR_RX_MCAST_DATA_OK_HI,
+               hw, port_id);
+       hw_stats->eth.rx_multicast += statistics;
+
+       /*Number of valid broadcast frames received,
+        *excluding control frames
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_RX_BCAST_DATA_OK_LO,
+               IPN3KE_25G_CNTR_RX_BCAST_DATA_OK_HI,
+               hw, port_id);
+       hw_stats->eth.rx_broadcast += statistics;
+
+       /*Number of valid unicast frames received,
+        *excluding control frames
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_RX_UCAST_DATA_OK_LO,
+               IPN3KE_25G_CNTR_RX_UCAST_DATA_OK_HI,
+               hw, port_id);
+       hw_stats->eth.rx_unicast += statistics;
+
+       /*Number of valid multicast frames received,
+        *excluding data frames
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_RX_MCAST_CTRL_LO,
+               IPN3KE_25G_CNTR_RX_MCAST_CTRL_HI,
+               hw, port_id);
+       hw_stats->eth.rx_multicast += statistics;
+
+       /*Number of valid broadcast frames received,
+        *excluding data frames
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_RX_BCAST_CTRL_LO,
+               IPN3KE_25G_CNTR_RX_BCAST_CTRL_HI,
+               hw, port_id);
+       hw_stats->eth.rx_broadcast += statistics;
+
+       /*Number of valid unicast frames received,
+        *excluding data frames
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_RX_UCAST_CTRL_LO,
+               IPN3KE_25G_CNTR_RX_UCAST_CTRL_HI,
+               hw, port_id);
+       hw_stats->eth.rx_unicast += statistics;
+
+       /*Number of received pause frames, with or without error
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_RX_PAUSE_LO,
+               IPN3KE_25G_CNTR_RX_PAUSE_HI,
+               hw, port_id);
+
+       /*Number of received runt packets. A runt is a packet of size
+        *less than 64 bytes but greater than eight bytes.
+        *If a packet is eight bytes or smaller, it is considered
+        *a decoding error and not a runt frame, and the IP core
+        *does not flag it nor count it as a runt.
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_CNTR_RX_RUNT_LO,
+               IPN3KE_25G_CNTR_RX_RUNT_HI,
+               hw, port_id);
+
+       /*Number of received payload bytes in frames with no FCS,
+        *undersized, oversized, or payload length errors.
+        *If VLAN detection is turned off for the RX MAC (bit [1] of the
+        *"RXMAC_CONTROL" register at offset 0x50A has the value of 1),
+        *the IP core counts the VLAN header bytes (4 bytes for VLAN and
+        *8 bytes for stacked VLAN) as payload bytes.
+        *This register is compliant with the requirements for
+        *aOctetsReceivedOK in section 5.2.2.1.14 of the IEEE Standard
+        *802.3-2008
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_RX_PAYLOAD_OCTETS_OK_LO,
+               IPN3KE_25G_RX_PAYLOAD_OCTETS_OK_HI,
+               hw, port_id);
+       hw_stats->eth.rx_bytes += statistics;
+
+       /*Number of received bytes in frames with no FCS, undersized,
+        *oversized, or payload length errors.
+        *This register is compliant with the requirements for
+        *ifInOctets in RFC3635 (Managed Objects for Ethernet-like
+        *Interface Types) and RX etherStatsOctets in RFC2819
+        *(Remote Network Monitoring Management Information Base
+        *(RMON)).
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_25G_RX_FRAME_OCTETS_OK_LO,
+               IPN3KE_25G_RX_FRAME_OCTETS_OK_HI,
+               hw, port_id);
+
+       /*resume Tx counter to real time
+        */
+       tmp = 0x00000000;
+       (*hw->f_mac_read)(hw,
+                       &tmp,
+                       IPN3KE_25G_TX_STATISTICS_CONFIG,
+                       port_id,
+                       0);
+       tmp &= 0xfffffffb;
+       (*hw->f_mac_write)(hw,
+                       tmp,
+                       IPN3KE_25G_TX_STATISTICS_CONFIG,
+                       port_id,
+                       0);
+
+       /*resume Rx counter to real time
+        */
+       tmp = 0x00000000;
+       (*hw->f_mac_read)(hw,
+                       &tmp,
+                       IPN3KE_25G_RX_STATISTICS_CONFIG,
+                       port_id,
+                       0);
+       tmp &= 0xfffffffb;
+       (*hw->f_mac_write)(hw,
+                       tmp,
+                       IPN3KE_25G_RX_STATISTICS_CONFIG,
+                       port_id,
+                       0);
+
        return 0;
 }
 
+static void
+ipn3ke_rpst_25g_lineside_tx_stats_reset(struct ipn3ke_hw *hw,
+uint16_t port_id)
+{
+       uint32_t tmp = 0x00000001;
+       /* Bit[0]: Software can set this bit to the value of 1
+        * to reset all of the TX statistics registers at the same time.
+        * This bit is selfclearing.
+        */
+       (*hw->f_mac_write)(hw,
+                       tmp,
+                       IPN3KE_25G_TX_STATISTICS_CONFIG,
+                       port_id,
+                       0);
+
+       while (tmp & 0x00000001) {
+               tmp = 0x00000000;
+               (*hw->f_mac_read)(hw,
+                               &tmp,
+                               IPN3KE_25G_TX_STATISTICS_CONFIG,
+                               port_id,
+                               0);
+               if (tmp & 0x00000001)
+                       usleep(5);
+               else
+                       return;
+       }
+}
+
+static void
+ipn3ke_rpst_25g_lineside_rx_stats_reset(struct ipn3ke_hw *hw,
+uint16_t port_id)
+{
+       uint32_t tmp = 0x00000001;
+       /* Bit[0]: Software can set this bit to the value of 1
+        * to reset all of the RX statistics registers at the same time.
+        * This bit is selfclearing.
+        */
+       (*hw->f_mac_write)(hw,
+                       tmp,
+                       IPN3KE_25G_RX_STATISTICS_CONFIG,
+                       port_id,
+                       0);
+
+       while (tmp & 0x00000001) {
+               tmp = 0x00000000;
+               (*hw->f_mac_read)(hw,
+                               &tmp,
+                               IPN3KE_25G_RX_STATISTICS_CONFIG,
+                               port_id,
+                               0);
+               if (tmp & 0x00000001)
+                       usleep(5);
+               else
+                       return;
+       }
+}
+
+static uint64_t
+ipn3ke_rpst_read_36bits_statistics_register(uint32_t addr_lo,
+uint32_t addr_hi, struct ipn3ke_hw *hw, uint16_t port_id)
+{
+       uint32_t statistics_lo = 0x00000000;
+       uint32_t statistics_hi = 0x00000000;
+       uint64_t statistics = 0x0000000000000000;
+
+       (*hw->f_mac_read)(hw,
+                       &statistics_lo,
+                       addr_lo,
+                       port_id,
+                       0);
+       (*hw->f_mac_read)(hw,
+                       &statistics_hi,
+                       addr_hi,
+                       port_id,
+                       0);
+       statistics_hi &= IPN3KE_10G_STATS_HI_VALID_MASK;
+       statistics += statistics_hi;
+       statistics = statistics << IPN3KE_REGISTER_WIDTH;
+       statistics += statistics_lo;
+       return statistics;
+}
+
 static int
-ipn3ke_rpst_xstats_get(__rte_unused struct rte_eth_dev *dev,
-       __rte_unused struct rte_eth_xstat *xstats, __rte_unused unsigned int n)
+ipn3ke_rpst_read_10g_lineside_stats_registers
+(struct ipn3ke_hw *hw,
+uint16_t port_id,
+struct ipn3ke_rpst_hw_port_stats *hw_stats,
+struct rte_eth_stats *stats)
 {
+       uint64_t statistics = 0;
+
+       memset(hw_stats, 0, sizeof(*hw_stats));
+       memset(stats, 0, sizeof(*stats));
+
+       /*36-bit statistics counter that collects the number of frames
+        *that are successfully transmitted, including control frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_TX_STATS_FRAME_OK_LO,
+               IPN3KE_10G_TX_STATS_FRAME_OK_HI,
+               hw, port_id);
+       stats->opackets = statistics;
+
+       /*36-bit statistics counter that collects the number of frames
+        *that are successfully received, including control frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_RX_STATS_FRAME_OK_LO,
+               IPN3KE_10G_RX_STATS_FRAME_OK_HI,
+               hw, port_id);
+       stats->ipackets = statistics;
+
+       /*36-bit statistics counter that collects the number of frames
+        *transmitted with error, including control frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_TX_STATS_FRAME_ERR_LO,
+               IPN3KE_10G_TX_STATS_FRAME_ERR_HI,
+               hw, port_id);
+       stats->oerrors = statistics;
+       hw_stats->eth.tx_errors = statistics;
+
+       /*36-bit statistics counter that collects the number of frames
+        *received with error, including control frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_RX_STATS_FRAME_ERR_LO,
+               IPN3KE_10G_RX_STATS_FRAME_ERR_HI,
+               hw, port_id);
+       stats->ierrors = statistics;
+       hw_stats->eth.rx_discards = statistics;
+
+       /*36-bit statistics counter that collects the number
+        *of RX frames with CRC error.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_RX_STATS_FRAME_CRC_ERR_LO,
+               IPN3KE_10G_RX_STATS_FRAME_CRC_ERR_HI,
+               hw, port_id);
+       hw_stats->crc_errors = statistics;
+
+       /*64-bit statistics counter that collects the payload length,
+        *including the bytes in control frames.
+        *The payload length is the number of data and padding bytes
+        *transmitted.
+        *If the tx_vlan_detection[0] register bit is set to 1,
+        *the VLAN and stacked VLAN tags are counted as part of
+        *the TX payload.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_TX_STATS_OCTETS_OK_LO,
+               IPN3KE_10G_TX_STATS_OCTETS_OK_HI,
+               hw, port_id);
+       stats->obytes = statistics;
+       hw_stats->eth.tx_bytes = statistics;
+
+       /*64-bit statistics counter that collects the payload length,
+        *including the bytes in control frames.
+        *The payload length is the number of data and padding bytes
+        *received.
+        *If the rx_vlan_detection[0] register bit is set to 1,
+        *the VLAN and stacked VLAN tags are counted as part of
+        *the RX payload.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_RX_STATS_OCTETS_OK_LO,
+               IPN3KE_10G_RX_STATS_OCTETS_OK_HI,
+               hw, port_id);
+       stats->ibytes = statistics;
+       hw_stats->eth.rx_bytes = statistics;
+
+       /*36-bit statistics counter that collects the number of
+        *valid pause frames transmitted.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_TX_STATS_PAUSE_MAC_CTRL_FRAMES_LO,
+               IPN3KE_10G_TX_STATS_PAUSE_MAC_CTRL_FRAMES_HI,
+               hw, port_id);
+
+       /*36-bit statistics counter that collects the number of
+        *valid pause frames received.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_RX_STATS_PAUSE_MAC_CTRL_FRAMES_LO,
+               IPN3KE_10G_RX_STATS_PAUSE_MAC_CTRL_FRAMES_HI,
+               hw, port_id);
+
+       /*36-bit statistics counter that collects the number of frames
+        *transmitted that are invalid and with error.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_TX_STATS_IF_ERRORS_LO,
+               IPN3KE_10G_TX_STATS_IF_ERRORS_HI,
+               hw, port_id);
+
+       /*36-bit statistics counter that collects the number of frames
+        *received that are invalid and with error.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_RX_STATS_IF_ERRORS_LO,
+               IPN3KE_10G_RX_STATS_IF_ERRORS_HI,
+               hw, port_id);
+
+       /*36-bit statistics counter that collects the number of
+        *good unicast frames transmitted,
+        *excluding control frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_TX_STATS_UNICAST_FRAME_OK_LO,
+               IPN3KE_10G_TX_STATS_UNICAST_FRAME_OK_HI,
+               hw, port_id);
+       hw_stats->eth.tx_unicast = statistics;
+
+       /*36-bit statistics counter that collects the number of
+        *good unicast frames received,
+        *excluding control frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_RX_STATS_UNICAST_FRAME_OK_LO,
+               IPN3KE_10G_RX_STATS_UNICAST_FRAME_OK_HI,
+               hw, port_id);
+       hw_stats->eth.rx_unicast = statistics;
+
+       /*36-bit statistics counter that collects the number of
+        *unicast frames transmitted with error,
+        *excluding control frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_TX_STATS_UNICAST_FRAME_ERR_LO,
+               IPN3KE_10G_TX_STATS_UNICAST_FRAME_ERR_HI,
+               hw, port_id);
+
+       /*36-bit statistics counter that collects the number of
+        *unicast frames received with error,
+        *excluding control frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_RX_STATS_UNICAST_FRAME_ERR_LO,
+               IPN3KE_10G_RX_STATS_UNICAST_FRAME_ERR_HI,
+               hw, port_id);
+
+       /*36-bit statistics counter that collects the number of
+        *good multicast frames transmitted,
+        *excluding control frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_TX_STATS_MULTICAST_FRAME_OK_LO,
+               IPN3KE_10G_TX_STATS_MULTICAST_FRAME_OK_HI,
+               hw, port_id);
+       hw_stats->eth.tx_multicast = statistics;
+
+       /*36-bit statistics counter that collects the number of
+        *good multicast frames received,
+        *excluding control frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_RX_STATS_MULTICAST_FRAME_OK_LO,
+               IPN3KE_10G_RX_STATS_MULTICAST_FRAME_OK_HI,
+               hw, port_id);
+       hw_stats->eth.rx_multicast = statistics;
+
+       /*36-bit statistics counter that collects the number of
+        *multicast frames transmitted with error,
+        *excluding control frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_TX_STATS_MULTICAST_FRAME_ERR_LO,
+               IPN3KE_10G_TX_STATS_MULTICAST_FRAME_ERR_HI,
+               hw, port_id);
+
+       /*36-bit statistics counter that collects the number
+        *of multicast frames received with error,
+        *excluding control frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_RX_STATS_MULTICAST_FRAME_ERR_LO,
+               IPN3KE_10G_RX_STATS_MULTICAST_FRAME_ERR_HI,
+               hw, port_id);
+
+       /*36-bit statistics counter that collects the number of
+        *good broadcast frames transmitted,
+        *excluding control frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_TX_STATS_BROADCAST_FRAME_OK_LO,
+               IPN3KE_10G_TX_STATS_BROADCAST_FRAME_OK_HI,
+               hw, port_id);
+       hw_stats->eth.tx_broadcast = statistics;
+
+       /*36-bit statistics counter that collects the number of
+        *good broadcast frames received,
+        *excluding control frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_RX_STATS_BROADCAST_FRAME_OK_LO,
+               IPN3KE_10G_RX_STATS_BROADCAST_FRAME_OK_HI,
+               hw, port_id);
+       hw_stats->eth.rx_broadcast = statistics;
+
+       /*36-bit statistics counter that collects the number
+        *of broadcast frames transmitted with error,
+        *excluding control frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_TX_STATS_BROADCAST_FRAME_ERR_LO,
+               IPN3KE_10G_TX_STATS_BROADCAST_FRAME_ERR_HI,
+               hw, port_id);
+
+       /*36-bit statistics counter that collects the number of
+        *broadcast frames received with error,
+        *excluding control frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_RX_STATS_BROADCAST_FRAME_ERR_LO,
+               IPN3KE_10G_RX_STATS_BROADCAST_FRAME_ERR_HI,
+               hw, port_id);
+
+       /*64-bit statistics counter that collects the total number of
+        *octets transmitted.
+        *This count includes good, errored, and invalid frames.
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_10G_TX_STATS_ETHER_STATS_OCTETS_LO,
+               IPN3KE_10G_TX_STATS_ETHER_STATS_OCTETS_HI,
+               hw, port_id);
+
+       /*64-bit statistics counter that collects the total number of
+        *octets received.
+        *This count includes good, errored, and invalid frames.
+        */
+       statistics = ipn3ke_rpst_read_64bits_statistics_register(
+               IPN3KE_10G_RX_STATS_ETHER_STATS_OCTETS_LO,
+               IPN3KE_10G_RX_STATS_ETHER_STATS_OCTETS_HI,
+               hw, port_id);
+
+       /*36-bit statistics counter that collects the total number of
+        *good, errored, and invalid frames transmitted.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_LO,
+               IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_HI,
+               hw, port_id);
+
+       /*36-bit statistics counter that collects the total number of
+        *good, errored, and invalid frames received.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_LO,
+               IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_HI,
+               hw, port_id);
+
+       /*36-bit statistics counter that collects the number of
+        *undersized TX frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_TX_STATS_ETHER_STATS_UNDER_SIZE_PKTS_LO,
+               IPN3KE_10G_TX_STATS_ETHER_STATS_UNDER_SIZE_PKTS_HI,
+               hw, port_id);
+
+       /*36-bit statistics counter that collects the number of
+        *undersized RX frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_RX_STATS_ETHER_STATS_UNDER_SIZE_PKTS_LO,
+               IPN3KE_10G_RX_STATS_ETHER_STATS_UNDER_SIZE_PKTS_HI,
+               hw, port_id);
+       hw_stats->rx_undersize = statistics;
+
+       /*36-bit statistics counter that collects the number of
+        *TX frames whose length exceeds the maximum frame length
+        *specified.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_TX_STATS_ETHER_STATS_OVER_SIZE_PKTS_LO,
+               IPN3KE_10G_TX_STATS_ETHER_STATS_OVER_SIZE_PKTS_HI,
+               hw, port_id);
+
+       /*36-bit statistics counter that collects the number of
+        *RX frames whose length exceeds the maximum frame length
+        *specified.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_RX_STATS_ETHER_STATS_OVER_SIZE_PKTS_LO,
+               IPN3KE_10G_RX_STATS_ETHER_STATS_OVER_SIZE_PKTS_HI,
+               hw, port_id);
+       hw_stats->rx_oversize = statistics;
+
+       /*36-bit statistics counter that collects the number of
+        *64-byte TX frames,
+        *including the CRC field
+        *but excluding the preamble and SFD bytes.
+        *This count includes good, errored, and invalid frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_64_OCTETS_LO,
+               IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_64_OCTETS_HI,
+               hw, port_id);
+       hw_stats->tx_size_64 = statistics;
+
+       /*36-bit statistics counter that collects the number of
+        *64-byte RX frames,
+        *including the CRC field
+        *but excluding the preamble and SFD bytes.
+        *This count includes good, errored, and invalid frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_64_OCTETS_LO,
+               IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_64_OCTETS_HI,
+               hw, port_id);
+       hw_stats->rx_size_64 = statistics;
+
+       /*36-bit statistics counter that collects the number of
+        *TX frames between the length of 65 and 127 bytes,
+        *including the CRC field
+        *but excluding the preamble and SFD bytes.
+        *This count includes good, errored, and invalid frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_65_127_OCTETS_LO,
+               IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_65_127_OCTETS_HI,
+               hw, port_id);
+       hw_stats->tx_size_65_127 = statistics;
+
+       /*36-bit statistics counter that collects the number of
+        *RX frames between the length of 65 and 127 bytes,
+        *including the CRC field
+        *but excluding the preamble and SFD bytes.
+        *This count includes good, errored, and invalid frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_65_127_OCTETS_LO,
+               IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_65_127_OCTETS_HI,
+               hw, port_id);
+       hw_stats->rx_size_65_127 = statistics;
+
+       /*36-bit statistics counter that collects the number of
+        *TX frames between the length of 128 and 255 bytes,
+        *including the CRC field
+        *but excluding the preamble and SFD bytes.
+        *This count includes good, errored, and invalid frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_128_255_OCTETS_LO,
+               IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_128_255_OCTETS_HI,
+               hw, port_id);
+       hw_stats->tx_size_128_255 = statistics;
+
+       /*36-bit statistics counter that collects the number of
+        *RX frames between the length of 128 and 255 bytes,
+        *including the CRC field
+        *but excluding the preamble and SFD bytes.
+        *This count includes good, errored, and invalid frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_128_255_OCTETS_LO,
+               IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_128_255_OCTETS_HI,
+               hw, port_id);
+       hw_stats->rx_size_128_255 = statistics;
+
+       /*36-bit statistics counter that collects the number of
+        *TX frames between the length of 256 and 511 bytes,
+        *including the CRC field
+        *but excluding the preamble and SFD bytes.
+        *This count includes good, errored, and invalid frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_256_511_OCTETS_LO,
+               IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_256_511_OCTETS_HI,
+               hw, port_id);
+       hw_stats->tx_size_256_511 = statistics;
+
+       /*36-bit statistics counter that collects the number of
+        *RX frames between the length of 256 and 511 bytes,
+        *including the CRC field
+        *but excluding the preamble and SFD bytes.
+        *This count includes good, errored, and invalid frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_256_511_OCTETS_LO,
+               IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_256_511_OCTETS_HI,
+               hw, port_id);
+       hw_stats->rx_size_256_511 = statistics;
+
+       /*36-bit statistics counter that collects the number of
+        *TX frames between the length of 512 and 1023 bytes,
+        *including the CRC field
+        *but excluding the preamble and SFD bytes.
+        *This count includes good, errored, and invalid frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_512_1023_OCTETS_LO,
+               IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_512_1023_OCTETS_HI,
+               hw, port_id);
+       hw_stats->tx_size_512_1023 = statistics;
+
+       /*36-bit statistics counter that collects the number of
+        *RX frames between the length of 512 and 1023 bytes,
+        *including the CRC field
+        *but excluding the preamble and SFD bytes.
+        *This count includes good, errored, and invalid frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_512_1023_OCTETS_LO,
+               IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_512_1023_OCTETS_HI,
+               hw, port_id);
+       hw_stats->rx_size_512_1023 = statistics;
+
+       /*36-bit statistics counter that collects the number of
+        *TX frames between the length of 1024 and 1518 bytes,
+        *including the CRC field but
+        *excluding the preamble and SFD bytes.
+        *This count includes good, errored, and invalid frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_1024_1518_OCTETS_LO,
+               IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_1024_1518_OCTETS_HI,
+               hw, port_id);
+       hw_stats->tx_size_1024_1518 = statistics;
+
+       /*36-bit statistics counter that collects the number of
+        *RX frames between the length of 1024 and 1518 bytes,
+        *including the CRC field
+        *but excluding the preamble and SFD bytes.
+        *This count includes good, errored, and invalid frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_1024_1518_OCTETS_LO,
+               IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_1024_1518_OCTETS_HI,
+               hw, port_id);
+       hw_stats->rx_size_1024_1518 = statistics;
+
+       /*36-bit statistics counter that collects the number of
+        *TX frames equal or more than the length of 1,519 bytes,
+        *including the CRC field
+        *but excluding the preamble and SFD bytes.
+        *This count includes good, errored, and invalid frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_1519_X_OCTETS_LO,
+               IPN3KE_10G_TX_STATS_ETHER_STATS_PKTS_1519_X_OCTETS_HI,
+               hw, port_id);
+       hw_stats->tx_size_1519_to_max = statistics;
+
+       /*36-bit statistics counter that collects the number of
+        *RX frames equal or more than the length of 1,519 bytes,
+        *including the CRC field
+        *but excluding the preamble and SFD bytes.
+        *This count includes good,
+        *errored, and invalid frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_1519_X_OCTETS_LO,
+               IPN3KE_10G_RX_STATS_ETHER_STATS_PKTS_1519_X_OCTETS_HI,
+               hw, port_id);
+       hw_stats->rx_size_big = statistics;
+
+       /*36-bit statistics counter that collects the total number of
+        *RX frames with length less than 64 bytes and CRC error.
+        *The MAC does not drop these frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_RX_STATS_ETHER_STATS_FRAGMENTS_LO,
+               IPN3KE_10G_RX_STATS_ETHER_STATS_FRAGMENTS_HI,
+               hw, port_id);
+
+       /*36-bit statistics counter that collects the number of
+        *oversized RX frames with CRC error.
+        *The MAC does not drop these frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_RX_STATS_ETHER_STATS_JABBERS_LO,
+               IPN3KE_10G_RX_STATS_ETHER_STATS_JABBERS_HI,
+               hw, port_id);
+
+       /*36-bit statistics counter that collects the number of
+        *RX frames with CRC error,
+        *whose length is between 64 and the maximum frame length
+        *specified in the register.
+        *The MAC does not drop these frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_RX_STATS_ETHER_STATS_CRC_ERR_LO,
+               IPN3KE_10G_RX_STATS_ETHER_STATS_CRC_ERR_HI,
+               hw, port_id);
+
+       /*36-bit statistics counter that collects the number of
+        *valid TX unicast control frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_TX_STATS_UNICAST_MAC_CTRL_FRAMES_LO,
+               IPN3KE_10G_TX_STATS_UNICAST_MAC_CTRL_FRAMES_HI,
+               hw, port_id);
+       hw_stats->eth.tx_unicast += statistics;
+
+       /*36-bit statistics counter that collects the number of
+        *valid RX unicast control frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_RX_STATS_UNICAST_MAC_CTRL_FRAMES_LO,
+               IPN3KE_10G_RX_STATS_UNICAST_MAC_CTRL_FRAMES_HI,
+               hw, port_id);
+       hw_stats->eth.rx_unicast += statistics;
+
+       /*36-bit statistics counter that collects the number of
+        *valid TX multicast control frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_TX_STATS_MULTICAST_MAC_CTRL_FRAMES_LO,
+               IPN3KE_10G_TX_STATS_MULTICAST_MAC_CTRL_FRAMES_HI,
+               hw, port_id);
+       hw_stats->eth.tx_multicast += statistics;
+
+       /*36-bit statistics counter that collects the number of
+        *valid RX multicast control frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_RX_STATS_MULTICAST_MAC_CTRL_FRAMES_LO,
+               IPN3KE_10G_RX_STATS_MULTICAST_MAC_CTRL_FRAMES_HI,
+               hw, port_id);
+       hw_stats->eth.rx_multicast += statistics;
+
+       /*36-bit statistics counter that collects the number of
+        *valid TX broadcast control frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_TX_STATS_BROADCAST_MAC_CTRL_FRAMES_LO,
+               IPN3KE_10G_TX_STATS_BROADCAST_MAC_CTRL_FRAMES_HI,
+               hw, port_id);
+       hw_stats->eth.tx_broadcast += statistics;
+
+       /*36-bit statistics counter that collects the number of
+        *valid RX broadcast control frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_RX_STATS_BROADCAST_MAC_CTRL_FRAMES_LO,
+               IPN3KE_10G_RX_STATS_BROADCAST_MAC_CTRL_FRAMES_HI,
+               hw, port_id);
+       hw_stats->eth.rx_broadcast += statistics;
+
+       /*36-bit statistics counter that collects the number of
+        *valid TX PFC frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_TX_STATS_PFC_MAC_CTRL_FRAMES_LO,
+               IPN3KE_10G_TX_STATS_PFC_MAC_CTRL_FRAMES_HI,
+               hw, port_id);
+
+       /*36-bit statistics counter that collects the number of
+        *valid RX PFC frames.
+        */
+       statistics = ipn3ke_rpst_read_36bits_statistics_register(
+               IPN3KE_10G_RX_STATS_PFC_MAC_CTRL_FRAMES_LO,
+               IPN3KE_10G_RX_STATS_PFC_MAC_CTRL_FRAMES_HI,
+               hw, port_id);
+
        return 0;
 }
 
+static void
+ipn3ke_rpst_10g_lineside_tx_stats_reset(struct ipn3ke_hw *hw,
+uint16_t port_id)
+{
+       uint32_t tmp;
+
+       /*Bit [0]: Set this register to 1 to clear all TX statistics
+        *counters.
+        *The IP core clears this bit when all counters are cleared.
+        *Bits [31:1]: Reserved.
+        */
+       tmp = 0x00000000;
+       (*hw->f_mac_read)(hw,
+               &tmp,
+               IPN3KE_10G_TX_STATS_CLR,
+               port_id,
+               0);
+       tmp |= 0x00000001;
+       (*hw->f_mac_write)(hw,
+               tmp,
+               IPN3KE_10G_TX_STATS_CLR,
+               port_id,
+               0);
+}
+
+static void
+ipn3ke_rpst_10g_lineside_rx_stats_reset(struct ipn3ke_hw *hw,
+uint16_t port_id)
+{
+       uint32_t tmp;
+
+       /*Bit [0]: Set this register to 1 to clear all RX statistics
+        *counters.
+        *The IP core clears this bit when all counters are cleared.
+        *Bits [31:1]: Reserved
+        */
+       tmp = 0x00000000;
+       (*hw->f_mac_read)(hw,
+               &tmp,
+               IPN3KE_10G_RX_STATS_CLR,
+               port_id,
+               0);
+       tmp |= 0x00000001;
+       (*hw->f_mac_write)(hw,
+               tmp,
+               IPN3KE_10G_RX_STATS_CLR,
+               port_id,
+               0);
+}
+
+static void
+ipn3ke_rpst_stats_reset(struct rte_eth_dev *ethdev)
+{
+       uint16_t port_id = 0;
+       char *ch;
+       int cnt = 0;
+       struct rte_afu_device *afu_dev = NULL;
+       struct ipn3ke_hw *hw = NULL;
+
+       if (!ethdev) {
+               IPN3KE_AFU_PMD_ERR("ethernet device to reset is NULL!");
+               return;
+       }
+
+       afu_dev = RTE_ETH_DEV_TO_AFU(ethdev);
+       if (!afu_dev) {
+               IPN3KE_AFU_PMD_ERR("afu device to reset is NULL!");
+               return;
+       }
+
+       if (!afu_dev->shared.data) {
+               IPN3KE_AFU_PMD_ERR("hardware data to reset is NULL!");
+               return;
+       }
+
+       hw = afu_dev->shared.data;
+
+       ch = ethdev->data->name;
+       if (!ch) {
+               IPN3KE_AFU_PMD_ERR("ethdev name is NULL!");
+               return;
+       }
+       while (ch) {
+               if (*ch == '_')
+                       cnt++;
+               ch++;
+               if (cnt == 3)
+                       break;
+       }
+       if (!ch) {
+               IPN3KE_AFU_PMD_ERR("Can not get port_id from ethdev name!");
+               return;
+       }
+       port_id = atoi(ch);
+
+       if (hw->retimer.mac_type == IFPGA_RAWDEV_RETIMER_MAC_TYPE_25GE_25GAUI) {
+               ipn3ke_rpst_25g_nic_side_tx_stats_reset(hw, port_id);
+               ipn3ke_rpst_25g_nic_side_rx_stats_reset(hw, port_id);
+               ipn3ke_rpst_25g_lineside_tx_stats_reset(hw, port_id);
+               ipn3ke_rpst_25g_lineside_rx_stats_reset(hw, port_id);
+       } else if (hw->retimer.mac_type ==
+                       IFPGA_RAWDEV_RETIMER_MAC_TYPE_10GE_XFI) {
+               ipn3ke_rpst_10g_nic_side_tx_stats_reset(hw, port_id);
+               ipn3ke_rpst_10g_nic_side_rx_stats_reset(hw, port_id);
+               ipn3ke_rpst_10g_lineside_tx_stats_reset(hw, port_id);
+               ipn3ke_rpst_10g_lineside_rx_stats_reset(hw, port_id);
+       }
+}
+
 static int
-ipn3ke_rpst_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
-               __rte_unused struct rte_eth_xstat_name *xstats_names,
-               __rte_unused unsigned int limit)
+ipn3ke_rpst_stats_get
+(struct rte_eth_dev *ethdev, struct rte_eth_stats *stats)
 {
+       uint16_t port_id = 0;
+       char *ch;
+       int cnt = 0;
+       int i = 0;
+       struct rte_afu_device *afu_dev = NULL;
+       struct ipn3ke_hw *hw = NULL;
+       struct ipn3ke_rpst_hw_port_stats hw_stats;
+
+       if (!ethdev) {
+               IPN3KE_AFU_PMD_ERR("ethernet device to get statistics is NULL");
+               return -EINVAL;
+       }
+       if (!stats) {
+               IPN3KE_AFU_PMD_ERR("Address to return statistics is NULL!");
+               return -EINVAL;
+       }
+
+       afu_dev = RTE_ETH_DEV_TO_AFU(ethdev);
+       if (!afu_dev) {
+               IPN3KE_AFU_PMD_ERR("afu device to get statistics is NULL!");
+               return -EINVAL;
+       }
+
+       if (!afu_dev->shared.data) {
+               IPN3KE_AFU_PMD_ERR("hardware data to get statistics is NULL!");
+               return -EINVAL;
+       }
+
+       hw = afu_dev->shared.data;
+
+       ch = ethdev->data->name;
+       if (!ch) {
+               IPN3KE_AFU_PMD_ERR("ethdev name is NULL!");
+               return -EINVAL;
+       }
+       while (ch) {
+               if (*ch == '_')
+                       cnt++;
+               ch++;
+               if (cnt == 3)
+                       break;
+       }
+       if (!ch) {
+               IPN3KE_AFU_PMD_ERR("Can not get port_id from ethdev name!");
+               return -EINVAL;
+       }
+       port_id = atoi(ch);
+
+       if (hw->retimer.mac_type == IFPGA_RAWDEV_RETIMER_MAC_TYPE_25GE_25GAUI) {
+               ipn3ke_rpst_read_25g_lineside_stats_registers(hw,
+                                                       port_id,
+                                                       &hw_stats);
+
+               stats->ipackets  = hw_stats.rx_size_64
+                                       + hw_stats.rx_size_65_127
+                                       + hw_stats.rx_size_128_255
+                                       + hw_stats.rx_size_256_511
+                                       + hw_stats.rx_size_512_1023
+                                       + hw_stats.rx_size_1024_1518
+                                       + hw_stats.rx_size_big
+                                       + hw_stats.rx_undersize
+                                       + hw_stats.rx_fragments
+                                       + hw_stats.rx_oversize
+                                       + hw_stats.rx_jabber;
+               stats->opackets  = hw_stats.tx_size_64
+                                       + hw_stats.tx_size_65_127
+                                       + hw_stats.tx_size_128_255
+                                       + hw_stats.tx_size_256_511
+                                       + hw_stats.tx_size_512_1023
+                                       + hw_stats.tx_size_1024_1518
+                                       + hw_stats.tx_size_1519_to_max;
+               stats->ibytes    = hw_stats.eth.rx_bytes;
+               stats->obytes    = hw_stats.eth.tx_bytes;
+               stats->imissed   = 0;
+               stats->ierrors   = hw_stats.eth.rx_discards
+                                       + hw_stats.eth.rx_unknown_protocol;
+               stats->oerrors   = hw_stats.eth.tx_discards
+                                       + hw_stats.eth.tx_errors;
+               stats->rx_nombuf = 0;
+               for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) {
+                       stats->q_ipackets[i] = 0;
+                       stats->q_opackets[i] = 0;
+                       stats->q_ibytes[i] = 0;
+                       stats->q_obytes[i] = 0;
+                       stats->q_errors[i] = 0;
+               }
+       } else {
+               ipn3ke_rpst_read_10g_lineside_stats_registers(hw,
+                                                       port_id,
+                                                       &hw_stats,
+                                                       stats);
+       }
+
        return 0;
 }
 
-static void
-ipn3ke_rpst_stats_reset(__rte_unused struct rte_eth_dev *ethdev)
+static int
+ipn3ke_rpst_xstats_get
+(struct rte_eth_dev *ethdev, struct rte_eth_xstat *xstats, unsigned int n)
 {
+       uint16_t port_id = 0;
+       char *ch = NULL;
+       int cnt = 0;
+       unsigned int i, count, prio;
+       struct rte_afu_device *afu_dev = NULL;
+       struct ipn3ke_hw *hw = NULL;
+       struct ipn3ke_rpst_hw_port_stats hw_stats;
+       struct rte_eth_stats stats;
+
+       if (!xstats)
+               return 0;
+
+       if (!ethdev) {
+               IPN3KE_AFU_PMD_ERR("ethernet device to get statistics is NULL");
+               return -EINVAL;
+       }
+
+       afu_dev = RTE_ETH_DEV_TO_AFU(ethdev);
+       if (!afu_dev) {
+               IPN3KE_AFU_PMD_ERR("afu device to get statistics is NULL!");
+               return -EINVAL;
+       }
+
+       if (!afu_dev->shared.data) {
+               IPN3KE_AFU_PMD_ERR("hardware data to get statistics is NULL!");
+               return -EINVAL;
+       }
+
+       hw = afu_dev->shared.data;
+
+       ch = ethdev->data->name;
+       if (!ch) {
+               IPN3KE_AFU_PMD_ERR("ethdev name is NULL!");
+               return -EINVAL;
+       }
+       while (ch) {
+               if (*ch == '_')
+                       cnt++;
+               ch++;
+               if (cnt == 3)
+                       break;
+       }
+       if (!ch) {
+               IPN3KE_AFU_PMD_ERR("Can not get port_id from ethdev name!");
+               return -EINVAL;
+       }
+       port_id = atoi(ch);
+
+       count = ipn3ke_rpst_xstats_calc_num();
+       if (n < count)
+               return count;
+
+       if (hw->retimer.mac_type == IFPGA_RAWDEV_RETIMER_MAC_TYPE_25GE_25GAUI) {
+               ipn3ke_rpst_read_25g_lineside_stats_registers(hw,
+                                                       port_id,
+                                                       &hw_stats);
+       } else {
+               ipn3ke_rpst_read_10g_lineside_stats_registers(hw,
+                                                       port_id,
+                                                       &hw_stats,
+                                                       &stats);
+       }
+
+       count = 0;
+
+       /* Get stats from ipn3ke_rpst_stats */
+       for (i = 0; i < IPN3KE_RPST_ETH_XSTATS_CNT; i++) {
+               xstats[count].value = *(uint64_t *)(((char *)&hw_stats.eth)
+                       + ipn3ke_rpst_stats_strings[i].offset);
+               xstats[count].id = count;
+               count++;
+       }
+
+       /* Get individiual stats from ipn3ke_rpst_hw_port */
+       for (i = 0; i < IPN3KE_RPST_HW_PORT_XSTATS_CNT; i++) {
+               xstats[count].value = *(uint64_t *)(((char *)(&hw_stats)) +
+                       ipn3ke_rpst_hw_port_strings[i].offset);
+               xstats[count].id = count;
+               count++;
+       }
+
+       /* Get individiual stats from ipn3ke_rpst_rxq_pri */
+       for (i = 0; i < IPN3KE_RPST_RXQ_PRIO_XSTATS_CNT; i++) {
+               for (prio = 0; prio < IPN3KE_RPST_PRIO_XSTATS_CNT; prio++) {
+                       xstats[count].value =
+                               *(uint64_t *)(((char *)(&hw_stats)) +
+                               ipn3ke_rpst_rxq_prio_strings[i].offset +
+                               (sizeof(uint64_t) * prio));
+                       xstats[count].id = count;
+                       count++;
+               }
+       }
+
+       /* Get individiual stats from ipn3ke_rpst_txq_prio */
+       for (i = 0; i < IPN3KE_RPST_TXQ_PRIO_XSTATS_CNT; i++) {
+               for (prio = 0; prio < IPN3KE_RPST_PRIO_XSTATS_CNT; prio++) {
+                       xstats[count].value =
+                               *(uint64_t *)(((char *)(&hw_stats)) +
+                               ipn3ke_rpst_txq_prio_strings[i].offset +
+                               (sizeof(uint64_t) * prio));
+                       xstats[count].id = count;
+                       count++;
+               }
+       }
+
+       return count;
+}
+
+static int
+ipn3ke_rpst_xstats_get_names
+(__rte_unused struct rte_eth_dev *dev,
+struct rte_eth_xstat_name *xstats_names,
+__rte_unused unsigned int limit)
+{
+       unsigned int count = 0;
+       unsigned int i, prio;
+
+       if (!xstats_names)
+               return ipn3ke_rpst_xstats_calc_num();
+
+       /* Note: limit checked in rte_eth_xstats_names() */
+
+       /* Get stats from ipn3ke_rpst_stats */
+       for (i = 0; i < IPN3KE_RPST_ETH_XSTATS_CNT; i++) {
+               snprintf(xstats_names[count].name,
+                        sizeof(xstats_names[count].name),
+                        "%s",
+                        ipn3ke_rpst_stats_strings[i].name);
+               count++;
+       }
+
+       /* Get individiual stats from ipn3ke_rpst_hw_port */
+       for (i = 0; i < IPN3KE_RPST_HW_PORT_XSTATS_CNT; i++) {
+               snprintf(xstats_names[count].name,
+                        sizeof(xstats_names[count].name),
+                        "%s",
+                        ipn3ke_rpst_hw_port_strings[i].name);
+               count++;
+       }
+
+       /* Get individiual stats from ipn3ke_rpst_rxq_pri */
+       for (i = 0; i < IPN3KE_RPST_RXQ_PRIO_XSTATS_CNT; i++) {
+               for (prio = 0; prio < 8; prio++) {
+                       snprintf(xstats_names[count].name,
+                                sizeof(xstats_names[count].name),
+                                "rx_priority%u_%s",
+                                prio,
+                                ipn3ke_rpst_rxq_prio_strings[i].name);
+                       count++;
+               }
+       }
+
+       /* Get individiual stats from ipn3ke_rpst_txq_prio */
+       for (i = 0; i < IPN3KE_RPST_TXQ_PRIO_XSTATS_CNT; i++) {
+               for (prio = 0; prio < 8; prio++) {
+                       snprintf(xstats_names[count].name,
+                                sizeof(xstats_names[count].name),
+                                "tx_priority%u_%s",
+                                prio,
+                                ipn3ke_rpst_txq_prio_strings[i].name);
+                       count++;
+               }
+       }
+       return count;
 }
 
 static void