diff mbox

[net-next,5/8] net: ethernet: annapurna: add statistics helper

Message ID 20170203181216.30214-6-antoine.tenart@free-electrons.com (mailing list archive)
State New, archived
Headers show

Commit Message

Antoine Tenart Feb. 3, 2017, 6:12 p.m. UTC
Add the ndo_get_stats64() helper in the Annapurna Labs Alpine Ethernet
driver.
---
 drivers/net/ethernet/annapurna/al_eth.c         |  36 ++++
 drivers/net/ethernet/annapurna/al_hw_eth.h      |   9 +
 drivers/net/ethernet/annapurna/al_hw_eth_main.c | 225 ++++++++++++++++++++++++
 3 files changed, 270 insertions(+)

Comments

Florian Fainelli Feb. 3, 2017, 7:34 p.m. UTC | #1
On 02/03/2017 10:12 AM, Antoine Tenart wrote:
> Add the ndo_get_stats64() helper in the Annapurna Labs Alpine Ethernet
> driver.
> ---
>  drivers/net/ethernet/annapurna/al_eth.c         |  36 ++++
>  drivers/net/ethernet/annapurna/al_hw_eth.h      |   9 +
>  drivers/net/ethernet/annapurna/al_hw_eth_main.c | 225 ++++++++++++++++++++++++
>  3 files changed, 270 insertions(+)
> 
> diff --git a/drivers/net/ethernet/annapurna/al_eth.c b/drivers/net/ethernet/annapurna/al_eth.c
> index 779a885de014..8dd84f66b5d1 100644
> --- a/drivers/net/ethernet/annapurna/al_eth.c
> +++ b/drivers/net/ethernet/annapurna/al_eth.c
> @@ -2388,6 +2388,41 @@ static void al_eth_set_msglevel(struct net_device *netdev, u32 value)
>  	adapter->msg_enable = value;
>  }
>  
> +static void al_eth_get_stats64(struct net_device *netdev,
> +			       struct rtnl_link_stats64 *stats)
> +{
> +	struct al_eth_adapter *adapter = netdev_priv(netdev);
> +	struct al_eth_mac_stats *mac_stats = &adapter->mac_stats;
> +
> +	if (!adapter->up)
> +		return NULL;
> +
> +	al_eth_mac_stats_get(&adapter->hw_adapter, mac_stats);

Are not you missing a reader synchronization here? Something like what
drivers/net/ethernet/realtek/8139too.c does for instance, especially if
this driver runs on ARM where you won't get "atomic" 64-bit reads (you
could, but it's more complicated).


> +
> +	stats->rx_packets = mac_stats->aFramesReceivedOK; /* including pause frames */
> +	stats->tx_packets = mac_stats->aFramesTransmittedOK; /* including pause frames */
> +	stats->rx_bytes = mac_stats->aOctetsReceivedOK;
> +	stats->tx_bytes = mac_stats->aOctetsTransmittedOK;
> +	stats->rx_dropped = 0;
> +	stats->multicast = mac_stats->ifInMulticastPkts;
> +	stats->collisions = 0;

Are these free running counters, or read on clear, or?

> +
> +	stats->rx_length_errors = (mac_stats->etherStatsUndersizePkts + /* good but short */
> +				   mac_stats->etherStatsFragments + /* short and bad*/
> +				   mac_stats->etherStatsJabbers + /* with crc errors */
> +				   mac_stats->etherStatsOversizePkts);
> +	stats->rx_crc_errors = mac_stats->aFrameCheckSequenceErrors;
> +	stats->rx_frame_errors = mac_stats->aAlignmentErrors;
> +	stats->rx_fifo_errors = mac_stats->etherStatsDropEvents;
> +	stats->rx_missed_errors = 0;
> +	stats->tx_window_errors = 0;
> +
> +	stats->rx_errors = mac_stats->ifInErrors;
> +	stats->tx_errors = mac_stats->ifOutErrors;
> +
> +	return stats;
> +}
> +
>  static void al_eth_get_drvinfo(struct net_device *dev,
>  			       struct ethtool_drvinfo *info)
>  {
> @@ -2763,6 +2798,7 @@ static const struct net_device_ops al_eth_netdev_ops = {
>  	.ndo_stop		= al_eth_close,
>  	.ndo_start_xmit		= al_eth_start_xmit,
>  	.ndo_select_queue	= al_eth_select_queue,
> +	.ndo_get_stats64	= al_eth_get_stats64,
>  	.ndo_do_ioctl		= al_eth_ioctl,
>  	.ndo_tx_timeout		= al_eth_tx_timeout,
>  	.ndo_change_mtu		= al_eth_change_mtu,
> diff --git a/drivers/net/ethernet/annapurna/al_hw_eth.h b/drivers/net/ethernet/annapurna/al_hw_eth.h
> index b2fc58793b3a..a44f3f200838 100644
> --- a/drivers/net/ethernet/annapurna/al_hw_eth.h
> +++ b/drivers/net/ethernet/annapurna/al_hw_eth.h
> @@ -982,6 +982,15 @@ struct al_eth_mac_stats {
>  };
>  
>  /*
> + * get mac statistics
> + * @param adapter pointer to the private structure.
> + * @param stats pointer to structure that will be filled with statistics.
> + *
> + * @return return 0 on success. otherwise on failure.
> + */
> +int al_eth_mac_stats_get(struct al_hw_eth_adapter *adapter, struct al_eth_mac_stats *stats);
> +
> +/*
>   * perform Function Level Reset RMN
>   *
>   * Addressing RMN: 714
> diff --git a/drivers/net/ethernet/annapurna/al_hw_eth_main.c b/drivers/net/ethernet/annapurna/al_hw_eth_main.c
> index abb9ffd09fbf..dac0c1e2a941 100644
> --- a/drivers/net/ethernet/annapurna/al_hw_eth_main.c
> +++ b/drivers/net/ethernet/annapurna/al_hw_eth_main.c
> @@ -2639,6 +2639,231 @@ int al_eth_flow_control_config(struct al_hw_eth_adapter *adapter,
>  	return 0;
>  }
>  
> +/* get statistics */
> +int al_eth_mac_stats_get(struct al_hw_eth_adapter *adapter, struct al_eth_mac_stats *stats)
> +{
> +	WARN_ON(!stats);
> +
> +	memset(stats, 0, sizeof(struct al_eth_mac_stats));
> +
> +	if (AL_ETH_IS_1G_MAC(adapter->mac_mode)) {
> +		struct al_eth_mac_1g_stats __iomem *reg_stats =
> +			&adapter->mac_regs_base->mac_1g.stats;
> +
> +		stats->ifInUcastPkts = readl(&reg_stats->ifInUcastPkts);
> +		stats->ifInMulticastPkts = readl(&reg_stats->ifInMulticastPkts);
> +		stats->ifInBroadcastPkts = readl(&reg_stats->ifInBroadcastPkts);
> +		stats->etherStatsPkts = readl(&reg_stats->etherStatsPkts);
> +		stats->ifOutUcastPkts = readl(&reg_stats->ifOutUcastPkts);
> +		stats->ifOutMulticastPkts = readl(&reg_stats->ifOutMulticastPkts);
> +		stats->ifOutBroadcastPkts = readl(&reg_stats->ifOutBroadcastPkts);
> +		stats->ifInErrors = readl(&reg_stats->ifInErrors);
> +		stats->ifOutErrors = readl(&reg_stats->ifOutErrors);
> +		stats->aFramesReceivedOK = readl(&reg_stats->aFramesReceivedOK);
> +		stats->aFramesTransmittedOK = readl(&reg_stats->aFramesTransmittedOK);
> +		stats->aOctetsReceivedOK = readl(&reg_stats->aOctetsReceivedOK);
> +		stats->aOctetsTransmittedOK = readl(&reg_stats->aOctetsTransmittedOK);
> +		stats->etherStatsUndersizePkts = readl(&reg_stats->etherStatsUndersizePkts);
> +		stats->etherStatsFragments = readl(&reg_stats->etherStatsFragments);
> +		stats->etherStatsJabbers = readl(&reg_stats->etherStatsJabbers);
> +		stats->etherStatsOversizePkts = readl(&reg_stats->etherStatsOversizePkts);
> +		stats->aFrameCheckSequenceErrors =
> +			readl(&reg_stats->aFrameCheckSequenceErrors);
> +		stats->aAlignmentErrors = readl(&reg_stats->aAlignmentErrors);
> +		stats->etherStatsDropEvents = readl(&reg_stats->etherStatsDropEvents);
> +		stats->aPAUSEMACCtrlFramesTransmitted =
> +			readl(&reg_stats->aPAUSEMACCtrlFramesTransmitted);
> +		stats->aPAUSEMACCtrlFramesReceived =
> +			readl(&reg_stats->aPAUSEMACCtrlFramesReceived);
> +		stats->aFrameTooLongErrors = 0; /* N/A */
> +		stats->aInRangeLengthErrors = 0; /* N/A */
> +		stats->VLANTransmittedOK = 0; /* N/A */
> +		stats->VLANReceivedOK = 0; /* N/A */
> +		stats->etherStatsOctets = readl(&reg_stats->etherStatsOctets);
> +		stats->etherStatsPkts64Octets = readl(&reg_stats->etherStatsPkts64Octets);
> +		stats->etherStatsPkts65to127Octets =
> +			readl(&reg_stats->etherStatsPkts65to127Octets);
> +		stats->etherStatsPkts128to255Octets =
> +			readl(&reg_stats->etherStatsPkts128to255Octets);
> +		stats->etherStatsPkts256to511Octets =
> +			readl(&reg_stats->etherStatsPkts256to511Octets);
> +		stats->etherStatsPkts512to1023Octets =
> +			readl(&reg_stats->etherStatsPkts512to1023Octets);
> +		stats->etherStatsPkts1024to1518Octets =
> +			readl(&reg_stats->etherStatsPkts1024to1518Octets);
> +		stats->etherStatsPkts1519toX = readl(&reg_stats->etherStatsPkts1519toX);
> +	} else if (AL_ETH_IS_10G_MAC(adapter->mac_mode) || AL_ETH_IS_25G_MAC(adapter->mac_mode)) {
> +		if (adapter->rev_id < AL_ETH_REV_ID_3) {
> +			struct al_eth_mac_10g_stats_v2 __iomem *reg_stats =
> +				&adapter->mac_regs_base->mac_10g.stats.v2;
> +			u64 octets;
> +

Using a structure to describe HW register is really ugly here, can't you
either come up with separate functions per generation of the hardware,
or even indirection tables with register offsets? Most statistics read
seem to be identical between generations of the HW, but their location
might differ.

> +			stats->ifInUcastPkts = readl(&reg_stats->ifInUcastPkts);
> +			stats->ifInMulticastPkts = readl(&reg_stats->ifInMulticastPkts);
> +			stats->ifInBroadcastPkts = readl(&reg_stats->ifInBroadcastPkts);
> +			stats->etherStatsPkts = readl(&reg_stats->etherStatsPkts);
> +			stats->ifOutUcastPkts = readl(&reg_stats->ifOutUcastPkts);
> +			stats->ifOutMulticastPkts = readl(&reg_stats->ifOutMulticastPkts);
> +			stats->ifOutBroadcastPkts = readl(&reg_stats->ifOutBroadcastPkts);
> +			stats->ifInErrors = readl(&reg_stats->ifInErrors);
> +			stats->ifOutErrors = readl(&reg_stats->ifOutErrors);
> +			stats->aFramesReceivedOK = readl(&reg_stats->aFramesReceivedOK);
> +			stats->aFramesTransmittedOK = readl(&reg_stats->aFramesTransmittedOK);
> +
> +			/* aOctetsReceivedOK = ifInOctets - 18 * aFramesReceivedOK - 4 * VLANReceivedOK */
> +			octets = readl(&reg_stats->ifInOctetsL);
> +			octets |= (u64)(readl(&reg_stats->ifInOctetsH)) << 32;
> +			octets -= 18 * stats->aFramesReceivedOK;
> +			octets -= 4 * readl(&reg_stats->VLANReceivedOK);
> +			stats->aOctetsReceivedOK = octets;
> +
> +			/* aOctetsTransmittedOK = ifOutOctets - 18 * aFramesTransmittedOK - 4 * VLANTransmittedOK */

What's that 18 for? Ethernet header + VLAN header? If so, express it
with appropriate constants

> +			octets = readl(&reg_stats->ifOutOctetsL);
> +			octets |= (u64)(readl(&reg_stats->ifOutOctetsH)) << 32;

upper_32_bits()

> +			octets -= 18 * stats->aFramesTransmittedOK;

What's that 18 for? Ethernet header + VLAN header? If so, express it
with appropriate constants

> +			octets -= 4 * readl(&reg_stats->VLANTransmittedOK);

4 = ETH_VLAN_HLEN

> +			stats->aOctetsTransmittedOK = octets;
> +
kernel test robot Feb. 3, 2017, 9:24 p.m. UTC | #2
Hi Antoine,

[auto build test WARNING on net-next/master]

url:    https://github.com/0day-ci/linux/commits/Antoine-Tenart/ARM-Alpine-Ethernet-support/20170204-022156
config: arm-allmodconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm 

All warnings (new ones prefixed by >>):

   drivers/net/ethernet/annapurna/al_eth.c: In function 'al_eth_restore_ethtool_params':
   drivers/net/ethernet/annapurna/al_eth.c:2139:15: warning: unused variable 'rx_usecs' [-Wunused-variable]
     unsigned int rx_usecs = adapter->rx_usecs;
                  ^~~~~~~~
   drivers/net/ethernet/annapurna/al_eth.c:2138:15: warning: unused variable 'tx_usecs' [-Wunused-variable]
     unsigned int tx_usecs = adapter->tx_usecs;
                  ^~~~~~~~
   In file included from include/uapi/linux/posix_types.h:4:0,
                    from include/uapi/linux/types.h:13,
                    from include/linux/types.h:5,
                    from include/linux/list.h:4,
                    from include/linux/module.h:9,
                    from drivers/net/ethernet/annapurna/al_eth.c:9:
   drivers/net/ethernet/annapurna/al_eth.c: In function 'al_eth_get_stats64':
>> include/linux/stddef.h:7:14: warning: 'return' with a value, in function returning void
    #define NULL ((void *)0)
                 ^
>> drivers/net/ethernet/annapurna/al_eth.c:2398:10: note: in expansion of macro 'NULL'
      return NULL;
             ^~~~
   drivers/net/ethernet/annapurna/al_eth.c:2391:13: note: declared here
    static void al_eth_get_stats64(struct net_device *netdev,
                ^~~~~~~~~~~~~~~~~~
>> drivers/net/ethernet/annapurna/al_eth.c:2423:9: warning: 'return' with a value, in function returning void
     return stats;
            ^~~~~
   drivers/net/ethernet/annapurna/al_eth.c:2391:13: note: declared here
    static void al_eth_get_stats64(struct net_device *netdev,
                ^~~~~~~~~~~~~~~~~~

vim +/NULL +2398 drivers/net/ethernet/annapurna/al_eth.c

  2392				       struct rtnl_link_stats64 *stats)
  2393	{
  2394		struct al_eth_adapter *adapter = netdev_priv(netdev);
  2395		struct al_eth_mac_stats *mac_stats = &adapter->mac_stats;
  2396	
  2397		if (!adapter->up)
> 2398			return NULL;
  2399	
  2400		al_eth_mac_stats_get(&adapter->hw_adapter, mac_stats);
  2401	
  2402		stats->rx_packets = mac_stats->aFramesReceivedOK; /* including pause frames */
  2403		stats->tx_packets = mac_stats->aFramesTransmittedOK; /* including pause frames */
  2404		stats->rx_bytes = mac_stats->aOctetsReceivedOK;
  2405		stats->tx_bytes = mac_stats->aOctetsTransmittedOK;
  2406		stats->rx_dropped = 0;
  2407		stats->multicast = mac_stats->ifInMulticastPkts;
  2408		stats->collisions = 0;
  2409	
  2410		stats->rx_length_errors = (mac_stats->etherStatsUndersizePkts + /* good but short */
  2411					   mac_stats->etherStatsFragments + /* short and bad*/
  2412					   mac_stats->etherStatsJabbers + /* with crc errors */
  2413					   mac_stats->etherStatsOversizePkts);
  2414		stats->rx_crc_errors = mac_stats->aFrameCheckSequenceErrors;
  2415		stats->rx_frame_errors = mac_stats->aAlignmentErrors;
  2416		stats->rx_fifo_errors = mac_stats->etherStatsDropEvents;
  2417		stats->rx_missed_errors = 0;
  2418		stats->tx_window_errors = 0;
  2419	
  2420		stats->rx_errors = mac_stats->ifInErrors;
  2421		stats->tx_errors = mac_stats->ifOutErrors;
  2422	
> 2423		return stats;
  2424	}
  2425	
  2426	static void al_eth_get_drvinfo(struct net_device *dev,

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
diff mbox

Patch

diff --git a/drivers/net/ethernet/annapurna/al_eth.c b/drivers/net/ethernet/annapurna/al_eth.c
index 779a885de014..8dd84f66b5d1 100644
--- a/drivers/net/ethernet/annapurna/al_eth.c
+++ b/drivers/net/ethernet/annapurna/al_eth.c
@@ -2388,6 +2388,41 @@  static void al_eth_set_msglevel(struct net_device *netdev, u32 value)
 	adapter->msg_enable = value;
 }
 
+static void al_eth_get_stats64(struct net_device *netdev,
+			       struct rtnl_link_stats64 *stats)
+{
+	struct al_eth_adapter *adapter = netdev_priv(netdev);
+	struct al_eth_mac_stats *mac_stats = &adapter->mac_stats;
+
+	if (!adapter->up)
+		return NULL;
+
+	al_eth_mac_stats_get(&adapter->hw_adapter, mac_stats);
+
+	stats->rx_packets = mac_stats->aFramesReceivedOK; /* including pause frames */
+	stats->tx_packets = mac_stats->aFramesTransmittedOK; /* including pause frames */
+	stats->rx_bytes = mac_stats->aOctetsReceivedOK;
+	stats->tx_bytes = mac_stats->aOctetsTransmittedOK;
+	stats->rx_dropped = 0;
+	stats->multicast = mac_stats->ifInMulticastPkts;
+	stats->collisions = 0;
+
+	stats->rx_length_errors = (mac_stats->etherStatsUndersizePkts + /* good but short */
+				   mac_stats->etherStatsFragments + /* short and bad*/
+				   mac_stats->etherStatsJabbers + /* with crc errors */
+				   mac_stats->etherStatsOversizePkts);
+	stats->rx_crc_errors = mac_stats->aFrameCheckSequenceErrors;
+	stats->rx_frame_errors = mac_stats->aAlignmentErrors;
+	stats->rx_fifo_errors = mac_stats->etherStatsDropEvents;
+	stats->rx_missed_errors = 0;
+	stats->tx_window_errors = 0;
+
+	stats->rx_errors = mac_stats->ifInErrors;
+	stats->tx_errors = mac_stats->ifOutErrors;
+
+	return stats;
+}
+
 static void al_eth_get_drvinfo(struct net_device *dev,
 			       struct ethtool_drvinfo *info)
 {
@@ -2763,6 +2798,7 @@  static const struct net_device_ops al_eth_netdev_ops = {
 	.ndo_stop		= al_eth_close,
 	.ndo_start_xmit		= al_eth_start_xmit,
 	.ndo_select_queue	= al_eth_select_queue,
+	.ndo_get_stats64	= al_eth_get_stats64,
 	.ndo_do_ioctl		= al_eth_ioctl,
 	.ndo_tx_timeout		= al_eth_tx_timeout,
 	.ndo_change_mtu		= al_eth_change_mtu,
diff --git a/drivers/net/ethernet/annapurna/al_hw_eth.h b/drivers/net/ethernet/annapurna/al_hw_eth.h
index b2fc58793b3a..a44f3f200838 100644
--- a/drivers/net/ethernet/annapurna/al_hw_eth.h
+++ b/drivers/net/ethernet/annapurna/al_hw_eth.h
@@ -982,6 +982,15 @@  struct al_eth_mac_stats {
 };
 
 /*
+ * get mac statistics
+ * @param adapter pointer to the private structure.
+ * @param stats pointer to structure that will be filled with statistics.
+ *
+ * @return return 0 on success. otherwise on failure.
+ */
+int al_eth_mac_stats_get(struct al_hw_eth_adapter *adapter, struct al_eth_mac_stats *stats);
+
+/*
  * perform Function Level Reset RMN
  *
  * Addressing RMN: 714
diff --git a/drivers/net/ethernet/annapurna/al_hw_eth_main.c b/drivers/net/ethernet/annapurna/al_hw_eth_main.c
index abb9ffd09fbf..dac0c1e2a941 100644
--- a/drivers/net/ethernet/annapurna/al_hw_eth_main.c
+++ b/drivers/net/ethernet/annapurna/al_hw_eth_main.c
@@ -2639,6 +2639,231 @@  int al_eth_flow_control_config(struct al_hw_eth_adapter *adapter,
 	return 0;
 }
 
+/* get statistics */
+int al_eth_mac_stats_get(struct al_hw_eth_adapter *adapter, struct al_eth_mac_stats *stats)
+{
+	WARN_ON(!stats);
+
+	memset(stats, 0, sizeof(struct al_eth_mac_stats));
+
+	if (AL_ETH_IS_1G_MAC(adapter->mac_mode)) {
+		struct al_eth_mac_1g_stats __iomem *reg_stats =
+			&adapter->mac_regs_base->mac_1g.stats;
+
+		stats->ifInUcastPkts = readl(&reg_stats->ifInUcastPkts);
+		stats->ifInMulticastPkts = readl(&reg_stats->ifInMulticastPkts);
+		stats->ifInBroadcastPkts = readl(&reg_stats->ifInBroadcastPkts);
+		stats->etherStatsPkts = readl(&reg_stats->etherStatsPkts);
+		stats->ifOutUcastPkts = readl(&reg_stats->ifOutUcastPkts);
+		stats->ifOutMulticastPkts = readl(&reg_stats->ifOutMulticastPkts);
+		stats->ifOutBroadcastPkts = readl(&reg_stats->ifOutBroadcastPkts);
+		stats->ifInErrors = readl(&reg_stats->ifInErrors);
+		stats->ifOutErrors = readl(&reg_stats->ifOutErrors);
+		stats->aFramesReceivedOK = readl(&reg_stats->aFramesReceivedOK);
+		stats->aFramesTransmittedOK = readl(&reg_stats->aFramesTransmittedOK);
+		stats->aOctetsReceivedOK = readl(&reg_stats->aOctetsReceivedOK);
+		stats->aOctetsTransmittedOK = readl(&reg_stats->aOctetsTransmittedOK);
+		stats->etherStatsUndersizePkts = readl(&reg_stats->etherStatsUndersizePkts);
+		stats->etherStatsFragments = readl(&reg_stats->etherStatsFragments);
+		stats->etherStatsJabbers = readl(&reg_stats->etherStatsJabbers);
+		stats->etherStatsOversizePkts = readl(&reg_stats->etherStatsOversizePkts);
+		stats->aFrameCheckSequenceErrors =
+			readl(&reg_stats->aFrameCheckSequenceErrors);
+		stats->aAlignmentErrors = readl(&reg_stats->aAlignmentErrors);
+		stats->etherStatsDropEvents = readl(&reg_stats->etherStatsDropEvents);
+		stats->aPAUSEMACCtrlFramesTransmitted =
+			readl(&reg_stats->aPAUSEMACCtrlFramesTransmitted);
+		stats->aPAUSEMACCtrlFramesReceived =
+			readl(&reg_stats->aPAUSEMACCtrlFramesReceived);
+		stats->aFrameTooLongErrors = 0; /* N/A */
+		stats->aInRangeLengthErrors = 0; /* N/A */
+		stats->VLANTransmittedOK = 0; /* N/A */
+		stats->VLANReceivedOK = 0; /* N/A */
+		stats->etherStatsOctets = readl(&reg_stats->etherStatsOctets);
+		stats->etherStatsPkts64Octets = readl(&reg_stats->etherStatsPkts64Octets);
+		stats->etherStatsPkts65to127Octets =
+			readl(&reg_stats->etherStatsPkts65to127Octets);
+		stats->etherStatsPkts128to255Octets =
+			readl(&reg_stats->etherStatsPkts128to255Octets);
+		stats->etherStatsPkts256to511Octets =
+			readl(&reg_stats->etherStatsPkts256to511Octets);
+		stats->etherStatsPkts512to1023Octets =
+			readl(&reg_stats->etherStatsPkts512to1023Octets);
+		stats->etherStatsPkts1024to1518Octets =
+			readl(&reg_stats->etherStatsPkts1024to1518Octets);
+		stats->etherStatsPkts1519toX = readl(&reg_stats->etherStatsPkts1519toX);
+	} else if (AL_ETH_IS_10G_MAC(adapter->mac_mode) || AL_ETH_IS_25G_MAC(adapter->mac_mode)) {
+		if (adapter->rev_id < AL_ETH_REV_ID_3) {
+			struct al_eth_mac_10g_stats_v2 __iomem *reg_stats =
+				&adapter->mac_regs_base->mac_10g.stats.v2;
+			u64 octets;
+
+			stats->ifInUcastPkts = readl(&reg_stats->ifInUcastPkts);
+			stats->ifInMulticastPkts = readl(&reg_stats->ifInMulticastPkts);
+			stats->ifInBroadcastPkts = readl(&reg_stats->ifInBroadcastPkts);
+			stats->etherStatsPkts = readl(&reg_stats->etherStatsPkts);
+			stats->ifOutUcastPkts = readl(&reg_stats->ifOutUcastPkts);
+			stats->ifOutMulticastPkts = readl(&reg_stats->ifOutMulticastPkts);
+			stats->ifOutBroadcastPkts = readl(&reg_stats->ifOutBroadcastPkts);
+			stats->ifInErrors = readl(&reg_stats->ifInErrors);
+			stats->ifOutErrors = readl(&reg_stats->ifOutErrors);
+			stats->aFramesReceivedOK = readl(&reg_stats->aFramesReceivedOK);
+			stats->aFramesTransmittedOK = readl(&reg_stats->aFramesTransmittedOK);
+
+			/* aOctetsReceivedOK = ifInOctets - 18 * aFramesReceivedOK - 4 * VLANReceivedOK */
+			octets = readl(&reg_stats->ifInOctetsL);
+			octets |= (u64)(readl(&reg_stats->ifInOctetsH)) << 32;
+			octets -= 18 * stats->aFramesReceivedOK;
+			octets -= 4 * readl(&reg_stats->VLANReceivedOK);
+			stats->aOctetsReceivedOK = octets;
+
+			/* aOctetsTransmittedOK = ifOutOctets - 18 * aFramesTransmittedOK - 4 * VLANTransmittedOK */
+			octets = readl(&reg_stats->ifOutOctetsL);
+			octets |= (u64)(readl(&reg_stats->ifOutOctetsH)) << 32;
+			octets -= 18 * stats->aFramesTransmittedOK;
+			octets -= 4 * readl(&reg_stats->VLANTransmittedOK);
+			stats->aOctetsTransmittedOK = octets;
+
+			stats->etherStatsUndersizePkts = readl(&reg_stats->etherStatsUndersizePkts);
+			stats->etherStatsFragments = readl(&reg_stats->etherStatsFragments);
+			stats->etherStatsJabbers = readl(&reg_stats->etherStatsJabbers);
+			stats->etherStatsOversizePkts = readl(&reg_stats->etherStatsOversizePkts);
+			stats->aFrameCheckSequenceErrors = readl(&reg_stats->aFrameCheckSequenceErrors);
+			stats->aAlignmentErrors = readl(&reg_stats->aAlignmentErrors);
+			stats->etherStatsDropEvents = readl(&reg_stats->etherStatsDropEvents);
+			stats->aPAUSEMACCtrlFramesTransmitted = readl(&reg_stats->aPAUSEMACCtrlFramesTransmitted);
+			stats->aPAUSEMACCtrlFramesReceived = readl(&reg_stats->aPAUSEMACCtrlFramesReceived);
+			stats->aFrameTooLongErrors = readl(&reg_stats->aFrameTooLongErrors);
+			stats->aInRangeLengthErrors = readl(&reg_stats->aInRangeLengthErrors);
+			stats->VLANTransmittedOK = readl(&reg_stats->VLANTransmittedOK);
+			stats->VLANReceivedOK = readl(&reg_stats->VLANReceivedOK);
+			stats->etherStatsOctets = readl(&reg_stats->etherStatsOctets);
+			stats->etherStatsPkts64Octets = readl(&reg_stats->etherStatsPkts64Octets);
+			stats->etherStatsPkts65to127Octets = readl(&reg_stats->etherStatsPkts65to127Octets);
+			stats->etherStatsPkts128to255Octets = readl(&reg_stats->etherStatsPkts128to255Octets);
+			stats->etherStatsPkts256to511Octets = readl(&reg_stats->etherStatsPkts256to511Octets);
+			stats->etherStatsPkts512to1023Octets = readl(&reg_stats->etherStatsPkts512to1023Octets);
+			stats->etherStatsPkts1024to1518Octets = readl(&reg_stats->etherStatsPkts1024to1518Octets);
+			stats->etherStatsPkts1519toX = readl(&reg_stats->etherStatsPkts1519toX);
+		} else {
+			struct al_eth_mac_10g_stats_v3_rx __iomem *reg_rx_stats =
+				&adapter->mac_regs_base->mac_10g.stats.v3.rx;
+			struct al_eth_mac_10g_stats_v3_tx __iomem *reg_tx_stats =
+				&adapter->mac_regs_base->mac_10g.stats.v3.tx;
+			u64 octets;
+
+			stats->ifInUcastPkts = readl(&reg_rx_stats->ifInUcastPkts);
+			stats->ifInMulticastPkts = readl(&reg_rx_stats->ifInMulticastPkts);
+			stats->ifInBroadcastPkts = readl(&reg_rx_stats->ifInBroadcastPkts);
+			stats->etherStatsPkts = readl(&reg_rx_stats->etherStatsPkts);
+			stats->ifOutUcastPkts = readl(&reg_tx_stats->ifUcastPkts);
+			stats->ifOutMulticastPkts = readl(&reg_tx_stats->ifMulticastPkts);
+			stats->ifOutBroadcastPkts = readl(&reg_tx_stats->ifBroadcastPkts);
+			stats->ifInErrors = readl(&reg_rx_stats->ifInErrors);
+			stats->ifOutErrors = readl(&reg_tx_stats->ifOutErrors);
+			stats->aFramesReceivedOK = readl(&reg_rx_stats->FramesOK);
+			stats->aFramesTransmittedOK = readl(&reg_tx_stats->FramesOK);
+
+			/* aOctetsReceivedOK = ifInOctets - 18 * aFramesReceivedOK - 4 * VLANReceivedOK */
+			octets = readl(&reg_rx_stats->ifOctetsL);
+			octets |= (u64)(readl(&reg_rx_stats->ifOctetsH)) << 32;
+			octets -= 18 * stats->aFramesReceivedOK;
+			octets -= 4 * readl(&reg_rx_stats->VLANOK);
+			stats->aOctetsReceivedOK = octets;
+
+			/* aOctetsTransmittedOK = ifOutOctets - 18 * aFramesTransmittedOK - 4 * VLANTransmittedOK */
+			octets = readl(&reg_tx_stats->ifOctetsL);
+			octets |= (u64)(readl(&reg_tx_stats->ifOctetsH)) << 32;
+			octets -= 18 * stats->aFramesTransmittedOK;
+			octets -= 4 * readl(&reg_tx_stats->VLANOK);
+			stats->aOctetsTransmittedOK = octets;
+
+			stats->etherStatsUndersizePkts = readl(&reg_rx_stats->etherStatsUndersizePkts);
+			stats->etherStatsFragments = readl(&reg_rx_stats->etherStatsFragments);
+			stats->etherStatsJabbers = readl(&reg_rx_stats->etherStatsJabbers);
+			stats->etherStatsOversizePkts = readl(&reg_rx_stats->etherStatsOversizePkts);
+			stats->aFrameCheckSequenceErrors = readl(&reg_rx_stats->CRCErrors);
+			stats->aAlignmentErrors = readl(&reg_rx_stats->aAlignmentErrors);
+			stats->etherStatsDropEvents = readl(&reg_rx_stats->etherStatsDropEvents);
+			stats->aPAUSEMACCtrlFramesTransmitted = readl(&reg_tx_stats->aPAUSEMACCtrlFrames);
+			stats->aPAUSEMACCtrlFramesReceived = readl(&reg_rx_stats->aPAUSEMACCtrlFrames);
+			stats->aFrameTooLongErrors = readl(&reg_rx_stats->aFrameTooLong);
+			stats->aInRangeLengthErrors = readl(&reg_rx_stats->aInRangeLengthErrors);
+			stats->VLANTransmittedOK = readl(&reg_tx_stats->VLANOK);
+			stats->VLANReceivedOK = readl(&reg_rx_stats->VLANOK);
+			stats->etherStatsOctets = readl(&reg_rx_stats->etherStatsOctets);
+			stats->etherStatsPkts64Octets = readl(&reg_rx_stats->etherStatsPkts64Octets);
+			stats->etherStatsPkts65to127Octets = readl(&reg_rx_stats->etherStatsPkts65to127Octets);
+			stats->etherStatsPkts128to255Octets = readl(&reg_rx_stats->etherStatsPkts128to255Octets);
+			stats->etherStatsPkts256to511Octets = readl(&reg_rx_stats->etherStatsPkts256to511Octets);
+			stats->etherStatsPkts512to1023Octets = readl(&reg_rx_stats->etherStatsPkts512to1023Octets);
+			stats->etherStatsPkts1024to1518Octets = readl(&reg_rx_stats->etherStatsPkts1024to1518Octets);
+			stats->etherStatsPkts1519toX = readl(&reg_rx_stats->etherStatsPkts1519toMax);
+		}
+	} else {
+		struct al_eth_mac_10g_stats_v3_rx __iomem *reg_rx_stats =
+			&adapter->mac_regs_base->mac_10g.stats.v3.rx;
+		struct al_eth_mac_10g_stats_v3_tx __iomem *reg_tx_stats =
+			&adapter->mac_regs_base->mac_10g.stats.v3.tx;
+		u64 octets;
+
+		/* 40G MAC statistics registers are the same, only read indirectly */
+		#define _40g_mac_reg_read32(field)	al_eth_40g_mac_reg_read(adapter,	\
+			((u8 *)(field)) - ((u8 *)&adapter->mac_regs_base->mac_10g))
+
+		stats->ifInUcastPkts = _40g_mac_reg_read32(&reg_rx_stats->ifInUcastPkts);
+		stats->ifInMulticastPkts = _40g_mac_reg_read32(&reg_rx_stats->ifInMulticastPkts);
+		stats->ifInBroadcastPkts = _40g_mac_reg_read32(&reg_rx_stats->ifInBroadcastPkts);
+		stats->etherStatsPkts = _40g_mac_reg_read32(&reg_rx_stats->etherStatsPkts);
+		stats->ifOutUcastPkts = _40g_mac_reg_read32(&reg_tx_stats->ifUcastPkts);
+		stats->ifOutMulticastPkts = _40g_mac_reg_read32(&reg_tx_stats->ifMulticastPkts);
+		stats->ifOutBroadcastPkts = _40g_mac_reg_read32(&reg_tx_stats->ifBroadcastPkts);
+		stats->ifInErrors = _40g_mac_reg_read32(&reg_rx_stats->ifInErrors);
+		stats->ifOutErrors = _40g_mac_reg_read32(&reg_tx_stats->ifOutErrors);
+		stats->aFramesReceivedOK = _40g_mac_reg_read32(&reg_rx_stats->FramesOK);
+		stats->aFramesTransmittedOK = _40g_mac_reg_read32(&reg_tx_stats->FramesOK);
+
+		/* aOctetsReceivedOK = ifInOctets - 18 * aFramesReceivedOK - 4 * VLANReceivedOK */
+		octets = _40g_mac_reg_read32(&reg_rx_stats->ifOctetsL);
+		octets |= (u64)(_40g_mac_reg_read32(&reg_rx_stats->ifOctetsH)) << 32;
+		octets -= 18 * stats->aFramesReceivedOK;
+		octets -= 4 * _40g_mac_reg_read32(&reg_rx_stats->VLANOK);
+		stats->aOctetsReceivedOK = octets;
+
+		/* aOctetsTransmittedOK = ifOutOctets - 18 * aFramesTransmittedOK - 4 * VLANTransmittedOK */
+		octets = _40g_mac_reg_read32(&reg_tx_stats->ifOctetsL);
+		octets |= (u64)(_40g_mac_reg_read32(&reg_tx_stats->ifOctetsH)) << 32;
+		octets -= 18 * stats->aFramesTransmittedOK;
+		octets -= 4 * _40g_mac_reg_read32(&reg_tx_stats->VLANOK);
+		stats->aOctetsTransmittedOK = octets;
+
+		stats->etherStatsUndersizePkts = _40g_mac_reg_read32(&reg_rx_stats->etherStatsUndersizePkts);
+		stats->etherStatsFragments = _40g_mac_reg_read32(&reg_rx_stats->etherStatsFragments);
+		stats->etherStatsJabbers = _40g_mac_reg_read32(&reg_rx_stats->etherStatsJabbers);
+		stats->etherStatsOversizePkts = _40g_mac_reg_read32(&reg_rx_stats->etherStatsOversizePkts);
+		stats->aFrameCheckSequenceErrors = _40g_mac_reg_read32(&reg_rx_stats->CRCErrors);
+		stats->aAlignmentErrors = _40g_mac_reg_read32(&reg_rx_stats->aAlignmentErrors);
+		stats->etherStatsDropEvents = _40g_mac_reg_read32(&reg_rx_stats->etherStatsDropEvents);
+		stats->aPAUSEMACCtrlFramesTransmitted = _40g_mac_reg_read32(&reg_tx_stats->aPAUSEMACCtrlFrames);
+		stats->aPAUSEMACCtrlFramesReceived = _40g_mac_reg_read32(&reg_rx_stats->aPAUSEMACCtrlFrames);
+		stats->aFrameTooLongErrors = _40g_mac_reg_read32(&reg_rx_stats->aFrameTooLong);
+		stats->aInRangeLengthErrors = _40g_mac_reg_read32(&reg_rx_stats->aInRangeLengthErrors);
+		stats->VLANTransmittedOK = _40g_mac_reg_read32(&reg_tx_stats->VLANOK);
+		stats->VLANReceivedOK = _40g_mac_reg_read32(&reg_rx_stats->VLANOK);
+		stats->etherStatsOctets = _40g_mac_reg_read32(&reg_rx_stats->etherStatsOctets);
+		stats->etherStatsPkts64Octets = _40g_mac_reg_read32(&reg_rx_stats->etherStatsPkts64Octets);
+		stats->etherStatsPkts65to127Octets = _40g_mac_reg_read32(&reg_rx_stats->etherStatsPkts65to127Octets);
+		stats->etherStatsPkts128to255Octets = _40g_mac_reg_read32(&reg_rx_stats->etherStatsPkts128to255Octets);
+		stats->etherStatsPkts256to511Octets = _40g_mac_reg_read32(&reg_rx_stats->etherStatsPkts256to511Octets);
+		stats->etherStatsPkts512to1023Octets = _40g_mac_reg_read32(&reg_rx_stats->etherStatsPkts512to1023Octets);
+		stats->etherStatsPkts1024to1518Octets = _40g_mac_reg_read32(&reg_rx_stats->etherStatsPkts1024to1518Octets);
+		stats->etherStatsPkts1519toX = _40g_mac_reg_read32(&reg_rx_stats->etherStatsPkts1519toMax);
+	}
+
+/*	stats->etherStatsPkts = 1; */
+	return 0;
+}
+
 /* Traffic control */
 
 int al_eth_flr_rmn(int (*pci_read_config_u32)(void *handle, int where, u32 *val),