Add support for ethtool standard device statistics grouping.
Support ethernet mac statistics grouping using eth-mac groups
parameter in ethtool command.
Signed-off-by: Rakesh Sankaranarayanan <rakesh.sankaranarayanan@microchip.com>
---
drivers/net/dsa/microchip/ksz_common.c | 13 ++++
drivers/net/dsa/microchip/ksz_common.h | 2 +
drivers/net/dsa/microchip/ksz_ethtool.c | 88 +++++++++++++++++++++++++
drivers/net/dsa/microchip/ksz_ethtool.h | 4 ++
4 files changed, 107 insertions(+)
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 9b13a38d553d..ceb3c4f120bd 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -160,6 +160,7 @@ static const struct ksz_dev_ops ksz8_dev_ops = {
.port_init_cnt = ksz8_port_init_cnt,
.get_rmon_stats = ksz8_get_rmon_stats,
.get_eth_ctrl_stats = ksz8_get_eth_ctrl_stats,
+ .get_eth_mac_stats = ksz8_get_eth_mac_stats,
.fdb_dump = ksz8_fdb_dump,
.mdb_add = ksz8_mdb_add,
.mdb_del = ksz8_mdb_del,
@@ -199,6 +200,7 @@ static const struct ksz_dev_ops ksz9477_dev_ops = {
.port_init_cnt = ksz9477_port_init_cnt,
.get_rmon_stats = ksz9477_get_rmon_stats,
.get_eth_ctrl_stats = ksz9477_get_eth_ctrl_stats,
+ .get_eth_mac_stats = ksz9477_get_eth_mac_stats,
.vlan_filtering = ksz9477_port_vlan_filtering,
.vlan_add = ksz9477_port_vlan_add,
.vlan_del = ksz9477_port_vlan_del,
@@ -237,6 +239,7 @@ static const struct ksz_dev_ops lan937x_dev_ops = {
.port_init_cnt = ksz9477_port_init_cnt,
.get_rmon_stats = ksz9477_get_rmon_stats,
.get_eth_ctrl_stats = ksz9477_get_eth_ctrl_stats,
+ .get_eth_mac_stats = ksz9477_get_eth_mac_stats,
.vlan_filtering = ksz9477_port_vlan_filtering,
.vlan_add = ksz9477_port_vlan_add,
.vlan_del = ksz9477_port_vlan_del,
@@ -1635,6 +1638,15 @@ static void ksz_get_eth_ctrl_stats(struct dsa_switch *ds, int port,
dev->dev_ops->get_eth_ctrl_stats(dev, port, ctrl_stats);
}
+static void ksz_get_eth_mac_stats(struct dsa_switch *ds, int port,
+ struct ethtool_eth_mac_stats *mac_stats)
+{
+ struct ksz_device *dev = ds->priv;
+
+ if (dev->dev_ops->get_eth_mac_stats)
+ dev->dev_ops->get_eth_mac_stats(dev, port, mac_stats);
+}
+
static void ksz_get_strings(struct dsa_switch *ds, int port,
u32 stringset, uint8_t *buf)
{
@@ -2887,6 +2899,7 @@ static const struct dsa_switch_ops ksz_switch_ops = {
.get_pause_stats = ksz_get_pause_stats,
.get_rmon_stats = ksz_get_rmon_stats,
.get_eth_ctrl_stats = ksz_get_eth_ctrl_stats,
+ .get_eth_mac_stats = ksz_get_eth_mac_stats,
.port_change_mtu = ksz_change_mtu,
.port_max_mtu = ksz_max_mtu,
};
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index 07627ff1a749..5b77f98483a9 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -344,6 +344,8 @@ struct ksz_dev_ops {
const struct ethtool_rmon_hist_range **ranges);
void (*get_eth_ctrl_stats)(struct ksz_device *dev, int port,
struct ethtool_eth_ctrl_stats *ctrl_stats);
+ void (*get_eth_mac_stats)(struct ksz_device *dev, int port,
+ struct ethtool_eth_mac_stats *mac_stats);
};
struct ksz_device *ksz_switch_alloc(struct device *base, void *priv);
diff --git a/drivers/net/dsa/microchip/ksz_ethtool.c b/drivers/net/dsa/microchip/ksz_ethtool.c
index 4c9ca21e1806..96529fea8e84 100644
--- a/drivers/net/dsa/microchip/ksz_ethtool.c
+++ b/drivers/net/dsa/microchip/ksz_ethtool.c
@@ -159,6 +159,50 @@ void ksz8_get_eth_ctrl_stats(struct ksz_device *dev, int port,
mutex_unlock(&mib->cnt_mutex);
}
+void ksz8_get_eth_mac_stats(struct ksz_device *dev, int port,
+ struct ethtool_eth_mac_stats *mac_stats)
+{
+ struct ksz_port_mib *mib;
+ u64 *ctr;
+
+ mib = &dev->ports[port].mib;
+
+ mutex_lock(&mib->cnt_mutex);
+ ctr = mib->counters;
+
+ while (mib->cnt_ptr < dev->info->mib_cnt) {
+ dev->dev_ops->r_mib_pkt(dev, port, mib->cnt_ptr,
+ NULL, &mib->counters[mib->cnt_ptr]);
+ ++mib->cnt_ptr;
+ }
+
+ mac_stats->FramesTransmittedOK = ctr[ksz8_tx_mcast] +
+ ctr[ksz8_tx_bcast] +
+ ctr[ksz8_tx_ucast] +
+ ctr[ksz8_tx_pause];
+ mac_stats->SingleCollisionFrames = ctr[ksz8_tx_single_col];
+ mac_stats->MultipleCollisionFrames = ctr[ksz8_tx_mult_col];
+ mac_stats->FramesReceivedOK = ctr[ksz8_rx_mcast] +
+ ctr[ksz8_rx_bcast] +
+ ctr[ksz8_rx_ucast] +
+ ctr[ksz8_rx_pause];
+ mac_stats->FrameCheckSequenceErrors = ctr[ksz8_rx_crc_err];
+ mac_stats->AlignmentErrors = ctr[ksz8_rx_align_err];
+ mac_stats->OctetsTransmittedOK = ctr[ksz8_tx_total_col];
+ mac_stats->FramesWithDeferredXmissions = ctr[ksz8_tx_deferred];
+ mac_stats->LateCollisions = ctr[ksz8_tx_late_col];
+ mac_stats->FramesAbortedDueToXSColls = ctr[ksz8_tx_exc_col];
+ mac_stats->MulticastFramesXmittedOK = ctr[ksz8_tx_mcast];
+ mac_stats->BroadcastFramesXmittedOK = ctr[ksz8_tx_bcast];
+ mac_stats->MulticastFramesReceivedOK = ctr[ksz8_rx_mcast];
+ mac_stats->BroadcastFramesReceivedOK = ctr[ksz8_rx_bcast];
+ mac_stats->InRangeLengthErrors = ctr[ksz8_rx_oversize];
+
+ mib->cnt_ptr = 0;
+
+ mutex_unlock(&mib->cnt_mutex);
+}
+
void ksz9477_get_rmon_stats(struct ksz_device *dev, int port,
struct ethtool_rmon_stats *rmon_stats,
const struct ethtool_rmon_hist_range **ranges)
@@ -218,3 +262,47 @@ void ksz9477_get_eth_ctrl_stats(struct ksz_device *dev, int port,
mutex_unlock(&mib->cnt_mutex);
}
+
+void ksz9477_get_eth_mac_stats(struct ksz_device *dev, int port,
+ struct ethtool_eth_mac_stats *mac_stats)
+{
+ struct ksz_port_mib *mib;
+ u64 *ctr;
+
+ mib = &dev->ports[port].mib;
+ ctr = mib->counters;
+
+ mutex_lock(&mib->cnt_mutex);
+
+ while (mib->cnt_ptr < dev->info->mib_cnt) {
+ dev->dev_ops->r_mib_pkt(dev, port, mib->cnt_ptr,
+ NULL, &mib->counters[mib->cnt_ptr]);
+ ++mib->cnt_ptr;
+ }
+
+ mac_stats->FramesTransmittedOK = ctr[ksz9477_tx_mcast] +
+ ctr[ksz9477_tx_bcast] +
+ ctr[ksz9477_tx_ucast] +
+ ctr[ksz9477_tx_pause];
+ mac_stats->SingleCollisionFrames = ctr[ksz9477_tx_single_col];
+ mac_stats->MultipleCollisionFrames = ctr[ksz9477_tx_mult_col];
+ mac_stats->FramesReceivedOK = ctr[ksz9477_rx_mcast] +
+ ctr[ksz9477_rx_bcast] +
+ ctr[ksz9477_rx_ucast] +
+ ctr[ksz9477_rx_pause];
+ mac_stats->FrameCheckSequenceErrors = ctr[ksz9477_rx_crc_err];
+ mac_stats->AlignmentErrors = ctr[ksz9477_rx_align_err];
+ mac_stats->OctetsTransmittedOK = ctr[ksz9477_tx_total_col];
+ mac_stats->FramesWithDeferredXmissions = ctr[ksz9477_tx_deferred];
+ mac_stats->LateCollisions = ctr[ksz9477_tx_late_col];
+ mac_stats->FramesAbortedDueToXSColls = ctr[ksz9477_tx_exc_col];
+ mac_stats->MulticastFramesXmittedOK = ctr[ksz9477_tx_mcast];
+ mac_stats->BroadcastFramesXmittedOK = ctr[ksz9477_tx_bcast];
+ mac_stats->MulticastFramesReceivedOK = ctr[ksz9477_rx_mcast];
+ mac_stats->BroadcastFramesReceivedOK = ctr[ksz9477_rx_bcast];
+ mac_stats->InRangeLengthErrors = ctr[ksz9477_rx_oversize];
+
+ mib->cnt_ptr = 0;
+
+ mutex_unlock(&mib->cnt_mutex);
+}
diff --git a/drivers/net/dsa/microchip/ksz_ethtool.h b/drivers/net/dsa/microchip/ksz_ethtool.h
index 18dc155d60b9..2dcfe8922b4e 100644
--- a/drivers/net/dsa/microchip/ksz_ethtool.h
+++ b/drivers/net/dsa/microchip/ksz_ethtool.h
@@ -13,10 +13,14 @@ void ksz8_get_rmon_stats(struct ksz_device *dev, int port,
const struct ethtool_rmon_hist_range **ranges);
void ksz8_get_eth_ctrl_stats(struct ksz_device *dev, int port,
struct ethtool_eth_ctrl_stats *ctrl_stats);
+void ksz8_get_eth_mac_stats(struct ksz_device *dev, int port,
+ struct ethtool_eth_mac_stats *mac_stats);
void ksz9477_get_rmon_stats(struct ksz_device *dev, int port,
struct ethtool_rmon_stats *rmon_stats,
const struct ethtool_rmon_hist_range **ranges);
void ksz9477_get_eth_ctrl_stats(struct ksz_device *dev, int port,
struct ethtool_eth_ctrl_stats *ctrl_stats);
+void ksz9477_get_eth_mac_stats(struct ksz_device *dev, int port,
+ struct ethtool_eth_mac_stats *mac_stats);
#endif
--
2.34.1
On Wed, 30 Nov 2022 18:59:00 +0530 Rakesh Sankaranarayanan wrote: > + mac_stats->FramesTransmittedOK = ctr[ksz9477_tx_mcast] + > + ctr[ksz9477_tx_bcast] + > + ctr[ksz9477_tx_ucast] + > + ctr[ksz9477_tx_pause]; do control frames count towards FramesTransmittedOK? Please check the standard I don't recall. > + mac_stats->SingleCollisionFrames = ctr[ksz9477_tx_single_col]; > + mac_stats->MultipleCollisionFrames = ctr[ksz9477_tx_mult_col]; > + mac_stats->FramesReceivedOK = ctr[ksz9477_rx_mcast] + > + ctr[ksz9477_rx_bcast] + > + ctr[ksz9477_rx_ucast] + > + ctr[ksz9477_rx_pause]; > + mac_stats->FrameCheckSequenceErrors = ctr[ksz9477_rx_crc_err]; > + mac_stats->AlignmentErrors = ctr[ksz9477_rx_align_err]; > + mac_stats->OctetsTransmittedOK = ctr[ksz9477_tx_total_col]; OctetsTransmittedOK = ksz9477_tx_total_col[lisons] ? > + mac_stats->InRangeLengthErrors = ctr[ksz9477_rx_oversize]; You use the same counter for RMON oversize statistic, the two definitely have different semantics, please check the standard and the datasheet. Remember that you don't have to fill in all the stats, if the HW does not maintain a matching statistic - leave the field be. Kernel will not report to user space unset fields.
Hi Jakub, Thanks for the review comment. On Thu, 2022-12-01 at 20:02 -0800, Jakub Kicinski wrote: > EXTERNAL EMAIL: Do not click links or open attachments unless you > know the content is safe > > On Wed, 30 Nov 2022 18:59:00 +0530 Rakesh Sankaranarayanan wrote: > > + mac_stats->FramesTransmittedOK = ctr[ksz9477_tx_mcast] + > > + ctr[ksz9477_tx_bcast] + > > + ctr[ksz9477_tx_ucast] + > > + ctr[ksz9477_tx_pause]; > > do control frames count towards FramesTransmittedOK? > Please check the standard I don't recall. > Yeah, I will check with the documentation. > > + mac_stats->SingleCollisionFrames = > > ctr[ksz9477_tx_single_col]; > > + mac_stats->MultipleCollisionFrames = > > ctr[ksz9477_tx_mult_col]; > > + mac_stats->FramesReceivedOK = ctr[ksz9477_rx_mcast] + > > + ctr[ksz9477_rx_bcast] + > > + ctr[ksz9477_rx_ucast] + > > + ctr[ksz9477_rx_pause]; > > + mac_stats->FrameCheckSequenceErrors = > > ctr[ksz9477_rx_crc_err]; > > + mac_stats->AlignmentErrors = ctr[ksz9477_rx_align_err]; > > + mac_stats->OctetsTransmittedOK = ctr[ksz9477_tx_total_col]; > > OctetsTransmittedOK = ksz9477_tx_total_col[lisons] ? > Sorry about this. It should be ksz9477_tx_total. I will review all the parameters again for avoiding such mistakes. > > + mac_stats->InRangeLengthErrors = ctr[ksz9477_rx_oversize]; > > You use the same counter for RMON oversize statistic, the two > definitely have different semantics, please check the standard > and the datasheet. > > Remember that you don't have to fill in all the stats, if the HW does > not maintain a matching statistic - leave the field be. Kernel will > not report to user space unset fields. Sure Jacub, I will review my code against documentation and submit the updated revision. Thanks, Rakesh S
On Fri, Dec 02, 2022 at 11:53:33AM +0000, Rakesh.Sankaranarayanan@microchip.com wrote: > Hi Jakub, > > Thanks for the review comment. > > On Thu, 2022-12-01 at 20:02 -0800, Jakub Kicinski wrote: > > EXTERNAL EMAIL: Do not click links or open attachments unless you > > know the content is safe > > > > On Wed, 30 Nov 2022 18:59:00 +0530 Rakesh Sankaranarayanan wrote: > > > + mac_stats->FramesTransmittedOK = ctr[ksz9477_tx_mcast] + > > > + ctr[ksz9477_tx_bcast] + > > > + ctr[ksz9477_tx_ucast] + > > > + ctr[ksz9477_tx_pause]; > > > > do control frames count towards FramesTransmittedOK? > > Please check the standard I don't recall. > > > Yeah, I will check with the documentation. Oleksij said that the hardware counts pause frames for the byte counters, so at least for consistency, they should be counted in frame counters too. https://patchwork.kernel.org/project/netdevbpf/patch/20221205052904.2834962-1-o.rempel@pengutronix.de/
© 2016 - 2025 Red Hat, Inc.