xref: /linux/drivers/net/dsa/netc/netc_ethtool.c (revision 25049d8b6e6b87f7ffcf53ce5ea1b51528b8677f)
1 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
2 /*
3  * NXP NETC switch driver
4  * Copyright 2025-2026 NXP
5  */
6 
7 #include <linux/ethtool_netlink.h>
8 
9 #include "netc_switch.h"
10 
11 static const struct ethtool_rmon_hist_range netc_rmon_ranges[] = {
12 	{   64,   64 },
13 	{   65,  127 },
14 	{  128,  255 },
15 	{  256,  511 },
16 	{  512, 1023 },
17 	{ 1024, 1522 },
18 	{ 1523, NETC_MAX_FRAME_LEN },
19 	{ }
20 };
21 
22 static void netc_port_pause_stats(struct netc_port *np, int mac,
23 				  struct ethtool_pause_stats *stats)
24 {
25 	if (mac && !np->caps.pmac)
26 		return;
27 
28 	stats->tx_pause_frames = netc_port_rd64(np, NETC_PM_TXPF(mac));
29 	stats->rx_pause_frames = netc_port_rd64(np, NETC_PM_RXPF(mac));
30 }
31 
32 void netc_port_get_pause_stats(struct dsa_switch *ds, int port,
33 			       struct ethtool_pause_stats *pause_stats)
34 {
35 	struct netc_port *np = NETC_PORT(ds, port);
36 	struct net_device *ndev;
37 
38 	switch (pause_stats->src) {
39 	case ETHTOOL_MAC_STATS_SRC_EMAC:
40 		netc_port_pause_stats(np, 0, pause_stats);
41 		break;
42 	case ETHTOOL_MAC_STATS_SRC_PMAC:
43 		netc_port_pause_stats(np, 1, pause_stats);
44 		break;
45 	case ETHTOOL_MAC_STATS_SRC_AGGREGATE:
46 		ndev = dsa_to_port(ds, port)->user;
47 		ethtool_aggregate_pause_stats(ndev, pause_stats);
48 		break;
49 	}
50 }
51 
52 static void netc_port_rmon_stats(struct netc_port *np, int mac,
53 				 struct ethtool_rmon_stats *stats)
54 {
55 	if (mac && !np->caps.pmac)
56 		return;
57 
58 	stats->undersize_pkts = netc_port_rd64(np, NETC_PM_RUND(mac));
59 	stats->oversize_pkts = netc_port_rd64(np, NETC_PM_ROVR(mac));
60 	stats->fragments = netc_port_rd64(np, NETC_PM_RFRG(mac));
61 	stats->jabbers = netc_port_rd64(np, NETC_PM_RJBR(mac));
62 
63 	stats->hist[0] = netc_port_rd64(np, NETC_PM_R64(mac));
64 	stats->hist[1] = netc_port_rd64(np, NETC_PM_R127(mac));
65 	stats->hist[2] = netc_port_rd64(np, NETC_PM_R255(mac));
66 	stats->hist[3] = netc_port_rd64(np, NETC_PM_R511(mac));
67 	stats->hist[4] = netc_port_rd64(np, NETC_PM_R1023(mac));
68 	stats->hist[5] = netc_port_rd64(np, NETC_PM_R1522(mac));
69 	stats->hist[6] = netc_port_rd64(np, NETC_PM_R1523X(mac));
70 
71 	stats->hist_tx[0] = netc_port_rd64(np, NETC_PM_T64(mac));
72 	stats->hist_tx[1] = netc_port_rd64(np, NETC_PM_T127(mac));
73 	stats->hist_tx[2] = netc_port_rd64(np, NETC_PM_T255(mac));
74 	stats->hist_tx[3] = netc_port_rd64(np, NETC_PM_T511(mac));
75 	stats->hist_tx[4] = netc_port_rd64(np, NETC_PM_T1023(mac));
76 	stats->hist_tx[5] = netc_port_rd64(np, NETC_PM_T1522(mac));
77 	stats->hist_tx[6] = netc_port_rd64(np, NETC_PM_T1523X(mac));
78 }
79 
80 void netc_port_get_rmon_stats(struct dsa_switch *ds, int port,
81 			      struct ethtool_rmon_stats *rmon_stats,
82 			      const struct ethtool_rmon_hist_range **ranges)
83 {
84 	struct netc_port *np = NETC_PORT(ds, port);
85 	struct net_device *ndev;
86 
87 	*ranges = netc_rmon_ranges;
88 
89 	switch (rmon_stats->src) {
90 	case ETHTOOL_MAC_STATS_SRC_EMAC:
91 		netc_port_rmon_stats(np, 0, rmon_stats);
92 		break;
93 	case ETHTOOL_MAC_STATS_SRC_PMAC:
94 		netc_port_rmon_stats(np, 1, rmon_stats);
95 		break;
96 	case ETHTOOL_MAC_STATS_SRC_AGGREGATE:
97 		ndev = dsa_to_port(ds, port)->user;
98 		ethtool_aggregate_rmon_stats(ndev, rmon_stats);
99 		break;
100 	}
101 }
102 
103 static void netc_port_ctrl_stats(struct netc_port *np, int mac,
104 				 struct ethtool_eth_ctrl_stats *stats)
105 {
106 	if (mac && !np->caps.pmac)
107 		return;
108 
109 	stats->MACControlFramesTransmitted =
110 		netc_port_rd64(np, NETC_PM_TCNP(mac));
111 	stats->MACControlFramesReceived =
112 		netc_port_rd64(np, NETC_PM_RCNP(mac));
113 }
114 
115 void netc_port_get_eth_ctrl_stats(struct dsa_switch *ds, int port,
116 				  struct ethtool_eth_ctrl_stats *ctrl_stats)
117 {
118 	struct netc_port *np = NETC_PORT(ds, port);
119 	struct net_device *ndev;
120 
121 	switch (ctrl_stats->src) {
122 	case ETHTOOL_MAC_STATS_SRC_EMAC:
123 		netc_port_ctrl_stats(np, 0, ctrl_stats);
124 		break;
125 	case ETHTOOL_MAC_STATS_SRC_PMAC:
126 		netc_port_ctrl_stats(np, 1, ctrl_stats);
127 		break;
128 	case ETHTOOL_MAC_STATS_SRC_AGGREGATE:
129 		ndev = dsa_to_port(ds, port)->user;
130 		ethtool_aggregate_ctrl_stats(ndev, ctrl_stats);
131 		break;
132 	}
133 }
134 
135 static void netc_port_mac_stats(struct netc_port *np, int mac,
136 				struct ethtool_eth_mac_stats *stats)
137 {
138 	if (mac && !np->caps.pmac)
139 		return;
140 
141 	stats->FramesTransmittedOK = netc_port_rd64(np, NETC_PM_TFRM(mac));
142 	stats->SingleCollisionFrames = netc_port_rd64(np, NETC_PM_TSCOL(mac));
143 	stats->MultipleCollisionFrames =
144 		netc_port_rd64(np, NETC_PM_TMCOL(mac));
145 	stats->FramesReceivedOK = netc_port_rd64(np, NETC_PM_RFRM(mac));
146 	stats->FrameCheckSequenceErrors =
147 		netc_port_rd64(np, NETC_PM_RFCS(mac));
148 	stats->AlignmentErrors = netc_port_rd64(np, NETC_PM_RALN(mac));
149 	stats->OctetsTransmittedOK = netc_port_rd64(np, NETC_PM_TEOCT(mac));
150 	stats->FramesWithDeferredXmissions =
151 		netc_port_rd64(np, NETC_PM_TDFR(mac));
152 	stats->LateCollisions = netc_port_rd64(np, NETC_PM_TLCOL(mac));
153 	stats->FramesAbortedDueToXSColls =
154 		netc_port_rd64(np, NETC_PM_TECOL(mac));
155 	stats->FramesLostDueToIntMACXmitError =
156 		netc_port_rd64(np, NETC_PM_TERR(mac));
157 	stats->OctetsReceivedOK = netc_port_rd64(np, NETC_PM_REOCT(mac));
158 	stats->FramesLostDueToIntMACRcvError =
159 		netc_port_rd64(np, NETC_PM_RDRNTP(mac));
160 	stats->MulticastFramesXmittedOK =
161 		netc_port_rd64(np, NETC_PM_TMCA(mac));
162 	stats->BroadcastFramesXmittedOK =
163 		netc_port_rd64(np, NETC_PM_TBCA(mac));
164 	stats->MulticastFramesReceivedOK =
165 		netc_port_rd64(np, NETC_PM_RMCA(mac));
166 	stats->BroadcastFramesReceivedOK =
167 		netc_port_rd64(np, NETC_PM_RBCA(mac));
168 	stats->FramesWithExcessiveDeferral =
169 		netc_port_rd64(np, NETC_PM_TEDFR(mac));
170 }
171 
172 void netc_port_get_eth_mac_stats(struct dsa_switch *ds, int port,
173 				 struct ethtool_eth_mac_stats *mac_stats)
174 {
175 	struct netc_port *np = NETC_PORT(ds, port);
176 	struct net_device *ndev;
177 
178 	switch (mac_stats->src) {
179 	case ETHTOOL_MAC_STATS_SRC_EMAC:
180 		netc_port_mac_stats(np, 0, mac_stats);
181 		break;
182 	case ETHTOOL_MAC_STATS_SRC_PMAC:
183 		netc_port_mac_stats(np, 1, mac_stats);
184 		break;
185 	case ETHTOOL_MAC_STATS_SRC_AGGREGATE:
186 		ndev = dsa_to_port(ds, port)->user;
187 		ethtool_aggregate_mac_stats(ndev, mac_stats);
188 		break;
189 	}
190 }
191