Commit 392c36e5 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'ehtool-fec-stats'



Jakub Kicinski says:

====================
ethtool: add standard FEC statistics

This set adds uAPI for reporting standard FEC statistics, and
implements it in a handful of drivers.

The statistics are taken from the IEEE standard, with one
extra seemingly popular but not standard statistics added.

The implementation is similar to that of the pause frame
statistics, user requests the stats by setting a bit
(ETHTOOL_FLAG_STATS) in the common ethtool header of
ETHTOOL_MSG_FEC_GET.

Since standard defines the statistics per lane what's
reported is both total and per-lane counters:

 # ethtool -I --show-fec eth0
 FEC parameters for eth0:
 Configured FEC encodings: None
 Active FEC encoding: None
 Statistics:
  corrected_blocks: 256
    Lane 0: 255
    Lane 1: 1
  uncorrectable_blocks: 145
    Lane 0: 128
    Lane 1: 17

v2: check for errors in mlx5 register access
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 38ebcf50 1703bb50
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -1302,6 +1302,7 @@ Kernel response contents:
  ``ETHTOOL_A_FEC_MODES``                bitset  configured modes
  ``ETHTOOL_A_FEC_AUTO``                 bool    FEC mode auto selection
  ``ETHTOOL_A_FEC_ACTIVE``               u32     index of active FEC mode
  ``ETHTOOL_A_FEC_STATS``                nested  FEC statistics
  =====================================  ======  ==========================

``ETHTOOL_A_FEC_ACTIVE`` is the bit index of the FEC link mode currently
@@ -1315,6 +1316,26 @@ This is equivalent to the ``ETHTOOL_FEC_AUTO`` bit of the ioctl interface.
``ETHTOOL_A_FEC_MODES`` carry the current FEC configuration using link mode
bits (rather than old ``ETHTOOL_FEC_*`` bits).

``ETHTOOL_A_FEC_STATS`` are reported if ``ETHTOOL_FLAG_STATS`` was set in
``ETHTOOL_A_HEADER_FLAGS``.
Each attribute carries an array of 64bit statistics. First entry in the array
contains the total number of events on the port, while the following entries
are counters corresponding to lanes/PCS instances. The number of entries in
the array will be:

+--------------+---------------------------------------------+
| `0`          | device does not support FEC statistics      |
+--------------+---------------------------------------------+
| `1`          | device does not support per-lane break down |
+--------------+---------------------------------------------+
| `1 + #lanes` | device has full support for FEC stats       |
+--------------+---------------------------------------------+

Drivers fill in the statistics in the following structure:

.. kernel-doc:: include/linux/ethtool.h
    :identifiers: ethtool_fec_stats

FEC_SET
=======

+2 −0
Original line number Diff line number Diff line
@@ -130,6 +130,7 @@ the `ETHTOOL_FLAG_STATS` flag in `ETHTOOL_A_HEADER_FLAGS`. Currently
statistics are supported in the following commands:

  - `ETHTOOL_MSG_PAUSE_GET`
  - `ETHTOOL_MSG_FEC_GET`

debugfs
-------
@@ -176,3 +177,4 @@ translated to netlink attributes when dumped. Drivers must not overwrite
the statistics they don't report with 0.

- ethtool_pause_stats()
- ethtool_fec_stats()
+15 −0
Original line number Diff line number Diff line
@@ -1930,6 +1930,20 @@ static int bnxt_get_fecparam(struct net_device *dev,
	return 0;
}

static void bnxt_get_fec_stats(struct net_device *dev,
			       struct ethtool_fec_stats *fec_stats)
{
	struct bnxt *bp = netdev_priv(dev);
	u64 *rx;

	if (BNXT_VF(bp) || !(bp->flags & BNXT_FLAG_PORT_STATS_EXT))
		return;

	rx = bp->rx_port_stats_ext.sw_stats;
	fec_stats->corrected_bits.total =
		*(rx + BNXT_RX_STATS_EXT_OFFSET(rx_corrected_bits));
}

static u32 bnxt_ethtool_forced_fec_to_fw(struct bnxt_link_info *link_info,
					 u32 fec)
{
@@ -3991,6 +4005,7 @@ const struct ethtool_ops bnxt_ethtool_ops = {
				     ETHTOOL_COALESCE_USE_ADAPTIVE_RX,
	.get_link_ksettings	= bnxt_get_link_ksettings,
	.set_link_ksettings	= bnxt_set_link_ksettings,
	.get_fec_stats		= bnxt_get_fec_stats,
	.get_fecparam		= bnxt_get_fecparam,
	.set_fecparam		= bnxt_set_fecparam,
	.get_pause_stats	= bnxt_get_pause_stats,
+9 −0
Original line number Diff line number Diff line
@@ -1602,6 +1602,14 @@ static int mlx5e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
	return mlx5_set_port_wol(mdev, mlx5_wol_mode);
}

static void mlx5e_get_fec_stats(struct net_device *netdev,
				struct ethtool_fec_stats *fec_stats)
{
	struct mlx5e_priv *priv = netdev_priv(netdev);

	mlx5e_stats_fec_get(priv, fec_stats);
}

static int mlx5e_get_fecparam(struct net_device *netdev,
			      struct ethtool_fecparam *fecparam)
{
@@ -2209,6 +2217,7 @@ const struct ethtool_ops mlx5e_ethtool_ops = {
	.self_test         = mlx5e_self_test,
	.get_msglevel      = mlx5e_get_msglevel,
	.set_msglevel      = mlx5e_set_msglevel,
	.get_fec_stats     = mlx5e_get_fec_stats,
	.get_fecparam      = mlx5e_get_fecparam,
	.set_fecparam      = mlx5e_set_fecparam,
};
+27 −2
Original line number Diff line number Diff line
@@ -768,10 +768,10 @@ static MLX5E_DECLARE_STATS_GRP_OP_UPDATE_STATS(802_3)
	mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPCNT, 0, 0);
}

#define MLX5E_READ_CTR64_BE_F(ptr, c)			\
#define MLX5E_READ_CTR64_BE_F(ptr, set, c)		\
	be64_to_cpu(*(__be64 *)((char *)ptr +		\
		MLX5_BYTE_OFF(ppcnt_reg,		\
			counter_set.eth_802_3_cntrs_grp_data_layout.c##_high)))
			      counter_set.set.c##_high)))

void mlx5e_stats_pause_get(struct mlx5e_priv *priv,
			   struct ethtool_pause_stats *pause_stats)
@@ -791,9 +791,11 @@ void mlx5e_stats_pause_get(struct mlx5e_priv *priv,

	pause_stats->tx_pause_frames =
		MLX5E_READ_CTR64_BE_F(ppcnt_ieee_802_3,
				      eth_802_3_cntrs_grp_data_layout,
				      a_pause_mac_ctrl_frames_transmitted);
	pause_stats->rx_pause_frames =
		MLX5E_READ_CTR64_BE_F(ppcnt_ieee_802_3,
				      eth_802_3_cntrs_grp_data_layout,
				      a_pause_mac_ctrl_frames_received);
}

@@ -1015,6 +1017,29 @@ static MLX5E_DECLARE_STATS_GRP_OP_UPDATE_STATS(phy)
	mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPCNT, 0, 0);
}

void mlx5e_stats_fec_get(struct mlx5e_priv *priv,
			 struct ethtool_fec_stats *fec_stats)
{
	u32 ppcnt_phy_statistical[MLX5_ST_SZ_DW(ppcnt_reg)];
	struct mlx5_core_dev *mdev = priv->mdev;
	u32 in[MLX5_ST_SZ_DW(ppcnt_reg)] = {0};
	int sz = MLX5_ST_SZ_BYTES(ppcnt_reg);

	if (!MLX5_CAP_PCAM_FEATURE(mdev, ppcnt_statistical_group))
		return;

	MLX5_SET(ppcnt_reg, in, local_port, 1);
	MLX5_SET(ppcnt_reg, in, grp, MLX5_PHYSICAL_LAYER_STATISTICAL_GROUP);
	if (mlx5_core_access_reg(mdev, in, sz, ppcnt_phy_statistical,
				 sz, MLX5_REG_PPCNT, 0, 0))
		return;

	fec_stats->corrected_bits.total =
		MLX5E_READ_CTR64_BE_F(ppcnt_phy_statistical,
				      phys_layer_statistical_cntrs,
				      phy_corrected_bits);
}

#define PPORT_ETH_EXT_OFF(c) \
	MLX5_BYTE_OFF(ppcnt_reg, \
		      counter_set.eth_extended_cntrs_grp_data_layout.c##_high)
Loading