Commit cf52bd23 authored by Vladimir Oltean's avatar Vladimir Oltean Committed by Jakub Kicinski
Browse files

net: enetc: add support for MAC Merge statistics counters



Add PF driver support for the following:

- Viewing the standardized MAC Merge layer counters.

- Viewing the standardized Ethernet MAC and RMON counters associated
  with the pMAC.

Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Link: https://lore.kernel.org/r/20230206094531.444988-2-vladimir.oltean@nxp.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent c7b9e808
Loading
Loading
Loading
Loading
+79 −5
Original line number Diff line number Diff line
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
/* Copyright 2017-2019 NXP */

#include <linux/ethtool_netlink.h>
#include <linux/net_tstamp.h>
#include <linux/module.h>
#include "enetc.h"
@@ -299,14 +300,32 @@ static void enetc_get_ethtool_stats(struct net_device *ndev,
		data[o++] = enetc_port_rd(hw, enetc_port_counters[i].reg);
}

static void enetc_pause_stats(struct enetc_hw *hw, int mac,
			      struct ethtool_pause_stats *pause_stats)
{
	pause_stats->tx_pause_frames = enetc_port_rd(hw, ENETC_PM_TXPF(mac));
	pause_stats->rx_pause_frames = enetc_port_rd(hw, ENETC_PM_RXPF(mac));
}

static void enetc_get_pause_stats(struct net_device *ndev,
				  struct ethtool_pause_stats *pause_stats)
{
	struct enetc_ndev_priv *priv = netdev_priv(ndev);
	struct enetc_hw *hw = &priv->si->hw;
	struct enetc_si *si = priv->si;

	pause_stats->tx_pause_frames = enetc_port_rd(hw, ENETC_PM_TXPF(0));
	pause_stats->rx_pause_frames = enetc_port_rd(hw, ENETC_PM_RXPF(0));
	switch (pause_stats->src) {
	case ETHTOOL_MAC_STATS_SRC_EMAC:
		enetc_pause_stats(hw, 0, pause_stats);
		break;
	case ETHTOOL_MAC_STATS_SRC_PMAC:
		if (si->hw_features & ENETC_SI_F_QBU)
			enetc_pause_stats(hw, 1, pause_stats);
		break;
	case ETHTOOL_MAC_STATS_SRC_AGGREGATE:
		ethtool_aggregate_pause_stats(ndev, pause_stats);
		break;
	}
}

static void enetc_mac_stats(struct enetc_hw *hw, int mac,
@@ -383,8 +402,20 @@ static void enetc_get_eth_mac_stats(struct net_device *ndev,
{
	struct enetc_ndev_priv *priv = netdev_priv(ndev);
	struct enetc_hw *hw = &priv->si->hw;
	struct enetc_si *si = priv->si;

	switch (mac_stats->src) {
	case ETHTOOL_MAC_STATS_SRC_EMAC:
		enetc_mac_stats(hw, 0, mac_stats);
		break;
	case ETHTOOL_MAC_STATS_SRC_PMAC:
		if (si->hw_features & ENETC_SI_F_QBU)
			enetc_mac_stats(hw, 1, mac_stats);
		break;
	case ETHTOOL_MAC_STATS_SRC_AGGREGATE:
		ethtool_aggregate_mac_stats(ndev, mac_stats);
		break;
	}
}

static void enetc_get_eth_ctrl_stats(struct net_device *ndev,
@@ -392,8 +423,20 @@ static void enetc_get_eth_ctrl_stats(struct net_device *ndev,
{
	struct enetc_ndev_priv *priv = netdev_priv(ndev);
	struct enetc_hw *hw = &priv->si->hw;
	struct enetc_si *si = priv->si;

	switch (ctrl_stats->src) {
	case ETHTOOL_MAC_STATS_SRC_EMAC:
		enetc_ctrl_stats(hw, 0, ctrl_stats);
		break;
	case ETHTOOL_MAC_STATS_SRC_PMAC:
		if (si->hw_features & ENETC_SI_F_QBU)
			enetc_ctrl_stats(hw, 1, ctrl_stats);
		break;
	case ETHTOOL_MAC_STATS_SRC_AGGREGATE:
		ethtool_aggregate_ctrl_stats(ndev, ctrl_stats);
		break;
	}
}

static void enetc_get_rmon_stats(struct net_device *ndev,
@@ -402,8 +445,20 @@ static void enetc_get_rmon_stats(struct net_device *ndev,
{
	struct enetc_ndev_priv *priv = netdev_priv(ndev);
	struct enetc_hw *hw = &priv->si->hw;
	struct enetc_si *si = priv->si;

	switch (rmon_stats->src) {
	case ETHTOOL_MAC_STATS_SRC_EMAC:
		enetc_rmon_stats(hw, 0, rmon_stats, ranges);
		break;
	case ETHTOOL_MAC_STATS_SRC_PMAC:
		if (si->hw_features & ENETC_SI_F_QBU)
			enetc_rmon_stats(hw, 1, rmon_stats, ranges);
		break;
	case ETHTOOL_MAC_STATS_SRC_AGGREGATE:
		ethtool_aggregate_rmon_stats(ndev, rmon_stats);
		break;
	}
}

#define ENETC_RSSHASH_L3 (RXH_L2DA | RXH_VLAN | RXH_L3_PROTO | RXH_IP_SRC | \
@@ -863,6 +918,24 @@ static int enetc_set_link_ksettings(struct net_device *dev,
	return phylink_ethtool_ksettings_set(priv->phylink, cmd);
}

static void enetc_get_mm_stats(struct net_device *ndev,
			       struct ethtool_mm_stats *s)
{
	struct enetc_ndev_priv *priv = netdev_priv(ndev);
	struct enetc_hw *hw = &priv->si->hw;
	struct enetc_si *si = priv->si;

	if (!(si->hw_features & ENETC_SI_F_QBU))
		return;

	s->MACMergeFrameAssErrorCount = enetc_port_rd(hw, ENETC_MMFAECR);
	s->MACMergeFrameSmdErrorCount = enetc_port_rd(hw, ENETC_MMFSECR);
	s->MACMergeFrameAssOkCount = enetc_port_rd(hw, ENETC_MMFAOCR);
	s->MACMergeFragCountRx = enetc_port_rd(hw, ENETC_MMFCRXR);
	s->MACMergeFragCountTx = enetc_port_rd(hw, ENETC_MMFCTXR);
	s->MACMergeHoldCount = enetc_port_rd(hw, ENETC_MMHCR);
}

static int enetc_get_mm(struct net_device *ndev, struct ethtool_mm_state *state)
{
	struct enetc_ndev_priv *priv = netdev_priv(ndev);
@@ -1037,6 +1110,7 @@ static const struct ethtool_ops enetc_pf_ethtool_ops = {
	.set_pauseparam = enetc_set_pauseparam,
	.get_mm = enetc_get_mm,
	.set_mm = enetc_set_mm,
	.get_mm_stats = enetc_get_mm_stats,
};

static const struct ethtool_ops enetc_vf_ethtool_ops = {
+6 −0
Original line number Diff line number Diff line
@@ -240,6 +240,12 @@ enum enetc_bdr_type {TX, RX};
#define ENETC_MMCSR_LPA		BIT(2) /* Local Preemption Active */
#define ENETC_MMCSR_LPE		BIT(1) /* Local Preemption Enabled */
#define ENETC_MMCSR_LPS		BIT(0) /* Local Preemption Supported */
#define ENETC_MMFAECR		0x1f08
#define ENETC_MMFSECR		0x1f0c
#define ENETC_MMFAOCR		0x1f10
#define ENETC_MMFCRXR		0x1f14
#define ENETC_MMFCTXR		0x1f18
#define ENETC_MMHCR		0x1f1c
#define ENETC_PTCMSDUR(n)	(0x2020 + (n) * 4) /* n = TC index [0..7] */

#define ENETC_PMAC_OFFSET	0x1000