2
2
/* Statistics for Ocelot switch family
3
3
*
4
4
* Copyright (c) 2017 Microsemi Corporation
5
+ * Copyright 2022 NXP
5
6
*/
6
7
#include <linux/spinlock.h>
7
8
#include <linux/mutex.h>
@@ -101,37 +102,32 @@ void ocelot_get_strings(struct ocelot *ocelot, int port, u32 sset, u8 *data)
101
102
}
102
103
EXPORT_SYMBOL (ocelot_get_strings );
103
104
104
- void ocelot_get_ethtool_stats (struct ocelot * ocelot , int port , u64 * data )
105
+ /* Update ocelot->stats for the given port and run the given callback */
106
+ static void ocelot_port_stats_run (struct ocelot * ocelot , int port , void * priv ,
107
+ void (* cb )(struct ocelot * ocelot , int port ,
108
+ void * priv ))
105
109
{
106
- int i , err ;
110
+ int err ;
107
111
108
112
mutex_lock (& ocelot -> stat_view_lock );
109
113
110
- /* check and update now */
111
114
err = ocelot_port_update_stats (ocelot , port );
115
+ if (err ) {
116
+ dev_err (ocelot -> dev , "Failed to update port %d stats: %pe\n" ,
117
+ port , ERR_PTR (err ));
118
+ goto out_unlock ;
119
+ }
112
120
113
121
spin_lock (& ocelot -> stats_lock );
114
122
115
123
ocelot_port_transfer_stats (ocelot , port );
116
-
117
- /* Copy all supported counters */
118
- for (i = 0 ; i < OCELOT_NUM_STATS ; i ++ ) {
119
- int index = port * OCELOT_NUM_STATS + i ;
120
-
121
- if (ocelot -> stats_layout [i ].name [0 ] == '\0' )
122
- continue ;
123
-
124
- * data ++ = ocelot -> stats [index ];
125
- }
124
+ cb (ocelot , port , priv );
126
125
127
126
spin_unlock (& ocelot -> stats_lock );
128
127
128
+ out_unlock :
129
129
mutex_unlock (& ocelot -> stat_view_lock );
130
-
131
- if (err )
132
- dev_err (ocelot -> dev , "Error %d updating ethtool stats\n" , err );
133
130
}
134
- EXPORT_SYMBOL (ocelot_get_ethtool_stats );
135
131
136
132
int ocelot_get_sset_count (struct ocelot * ocelot , int port , int sset )
137
133
{
@@ -148,6 +144,177 @@ int ocelot_get_sset_count(struct ocelot *ocelot, int port, int sset)
148
144
}
149
145
EXPORT_SYMBOL (ocelot_get_sset_count );
150
146
147
+ static void ocelot_port_ethtool_stats_cb (struct ocelot * ocelot , int port ,
148
+ void * priv )
149
+ {
150
+ u64 * data = priv ;
151
+ int i ;
152
+
153
+ /* Copy all supported counters */
154
+ for (i = 0 ; i < OCELOT_NUM_STATS ; i ++ ) {
155
+ int index = port * OCELOT_NUM_STATS + i ;
156
+
157
+ if (ocelot -> stats_layout [i ].name [0 ] == '\0' )
158
+ continue ;
159
+
160
+ * data ++ = ocelot -> stats [index ];
161
+ }
162
+ }
163
+
164
+ void ocelot_get_ethtool_stats (struct ocelot * ocelot , int port , u64 * data )
165
+ {
166
+ ocelot_port_stats_run (ocelot , port , data , ocelot_port_ethtool_stats_cb );
167
+ }
168
+ EXPORT_SYMBOL (ocelot_get_ethtool_stats );
169
+
170
+ static void ocelot_port_pause_stats_cb (struct ocelot * ocelot , int port , void * priv )
171
+ {
172
+ u64 * s = & ocelot -> stats [port * OCELOT_NUM_STATS ];
173
+ struct ethtool_pause_stats * pause_stats = priv ;
174
+
175
+ pause_stats -> tx_pause_frames = s [OCELOT_STAT_TX_PAUSE ];
176
+ pause_stats -> rx_pause_frames = s [OCELOT_STAT_RX_PAUSE ];
177
+ }
178
+
179
+ void ocelot_port_get_pause_stats (struct ocelot * ocelot , int port ,
180
+ struct ethtool_pause_stats * pause_stats )
181
+ {
182
+ ocelot_port_stats_run (ocelot , port , pause_stats ,
183
+ ocelot_port_pause_stats_cb );
184
+ }
185
+ EXPORT_SYMBOL_GPL (ocelot_port_get_pause_stats );
186
+
187
+ static const struct ethtool_rmon_hist_range ocelot_rmon_ranges [] = {
188
+ { 64 , 64 },
189
+ { 65 , 127 },
190
+ { 128 , 255 },
191
+ { 256 , 511 },
192
+ { 512 , 1023 },
193
+ { 1024 , 1526 },
194
+ { 1527 , 65535 },
195
+ {},
196
+ };
197
+
198
+ static void ocelot_port_rmon_stats_cb (struct ocelot * ocelot , int port , void * priv )
199
+ {
200
+ u64 * s = & ocelot -> stats [port * OCELOT_NUM_STATS ];
201
+ struct ethtool_rmon_stats * rmon_stats = priv ;
202
+
203
+ rmon_stats -> undersize_pkts = s [OCELOT_STAT_RX_SHORTS ];
204
+ rmon_stats -> oversize_pkts = s [OCELOT_STAT_RX_LONGS ];
205
+ rmon_stats -> fragments = s [OCELOT_STAT_RX_FRAGMENTS ];
206
+ rmon_stats -> jabbers = s [OCELOT_STAT_RX_JABBERS ];
207
+
208
+ rmon_stats -> hist [0 ] = s [OCELOT_STAT_RX_64 ];
209
+ rmon_stats -> hist [1 ] = s [OCELOT_STAT_RX_65_127 ];
210
+ rmon_stats -> hist [2 ] = s [OCELOT_STAT_RX_128_255 ];
211
+ rmon_stats -> hist [3 ] = s [OCELOT_STAT_RX_256_511 ];
212
+ rmon_stats -> hist [4 ] = s [OCELOT_STAT_RX_512_1023 ];
213
+ rmon_stats -> hist [5 ] = s [OCELOT_STAT_RX_1024_1526 ];
214
+ rmon_stats -> hist [6 ] = s [OCELOT_STAT_RX_1527_MAX ];
215
+
216
+ rmon_stats -> hist_tx [0 ] = s [OCELOT_STAT_TX_64 ];
217
+ rmon_stats -> hist_tx [1 ] = s [OCELOT_STAT_TX_65_127 ];
218
+ rmon_stats -> hist_tx [2 ] = s [OCELOT_STAT_TX_128_255 ];
219
+ rmon_stats -> hist_tx [3 ] = s [OCELOT_STAT_TX_128_255 ];
220
+ rmon_stats -> hist_tx [4 ] = s [OCELOT_STAT_TX_256_511 ];
221
+ rmon_stats -> hist_tx [5 ] = s [OCELOT_STAT_TX_512_1023 ];
222
+ rmon_stats -> hist_tx [6 ] = s [OCELOT_STAT_TX_1024_1526 ];
223
+ }
224
+
225
+ void ocelot_port_get_rmon_stats (struct ocelot * ocelot , int port ,
226
+ struct ethtool_rmon_stats * rmon_stats ,
227
+ const struct ethtool_rmon_hist_range * * ranges )
228
+ {
229
+ * ranges = ocelot_rmon_ranges ;
230
+
231
+ ocelot_port_stats_run (ocelot , port , rmon_stats ,
232
+ ocelot_port_rmon_stats_cb );
233
+ }
234
+ EXPORT_SYMBOL_GPL (ocelot_port_get_rmon_stats );
235
+
236
+ static void ocelot_port_ctrl_stats_cb (struct ocelot * ocelot , int port , void * priv )
237
+ {
238
+ u64 * s = & ocelot -> stats [port * OCELOT_NUM_STATS ];
239
+ struct ethtool_eth_ctrl_stats * ctrl_stats = priv ;
240
+
241
+ ctrl_stats -> MACControlFramesReceived = s [OCELOT_STAT_RX_CONTROL ];
242
+ }
243
+
244
+ void ocelot_port_get_eth_ctrl_stats (struct ocelot * ocelot , int port ,
245
+ struct ethtool_eth_ctrl_stats * ctrl_stats )
246
+ {
247
+ ocelot_port_stats_run (ocelot , port , ctrl_stats ,
248
+ ocelot_port_ctrl_stats_cb );
249
+ }
250
+ EXPORT_SYMBOL_GPL (ocelot_port_get_eth_ctrl_stats );
251
+
252
+ static void ocelot_port_mac_stats_cb (struct ocelot * ocelot , int port , void * priv )
253
+ {
254
+ u64 * s = & ocelot -> stats [port * OCELOT_NUM_STATS ];
255
+ struct ethtool_eth_mac_stats * mac_stats = priv ;
256
+
257
+ mac_stats -> OctetsTransmittedOK = s [OCELOT_STAT_TX_OCTETS ];
258
+ mac_stats -> FramesTransmittedOK = s [OCELOT_STAT_TX_64 ] +
259
+ s [OCELOT_STAT_TX_65_127 ] +
260
+ s [OCELOT_STAT_TX_128_255 ] +
261
+ s [OCELOT_STAT_TX_256_511 ] +
262
+ s [OCELOT_STAT_TX_512_1023 ] +
263
+ s [OCELOT_STAT_TX_1024_1526 ] +
264
+ s [OCELOT_STAT_TX_1527_MAX ];
265
+ mac_stats -> OctetsReceivedOK = s [OCELOT_STAT_RX_OCTETS ];
266
+ mac_stats -> FramesReceivedOK = s [OCELOT_STAT_RX_GREEN_PRIO_0 ] +
267
+ s [OCELOT_STAT_RX_GREEN_PRIO_1 ] +
268
+ s [OCELOT_STAT_RX_GREEN_PRIO_2 ] +
269
+ s [OCELOT_STAT_RX_GREEN_PRIO_3 ] +
270
+ s [OCELOT_STAT_RX_GREEN_PRIO_4 ] +
271
+ s [OCELOT_STAT_RX_GREEN_PRIO_5 ] +
272
+ s [OCELOT_STAT_RX_GREEN_PRIO_6 ] +
273
+ s [OCELOT_STAT_RX_GREEN_PRIO_7 ] +
274
+ s [OCELOT_STAT_RX_YELLOW_PRIO_0 ] +
275
+ s [OCELOT_STAT_RX_YELLOW_PRIO_1 ] +
276
+ s [OCELOT_STAT_RX_YELLOW_PRIO_2 ] +
277
+ s [OCELOT_STAT_RX_YELLOW_PRIO_3 ] +
278
+ s [OCELOT_STAT_RX_YELLOW_PRIO_4 ] +
279
+ s [OCELOT_STAT_RX_YELLOW_PRIO_5 ] +
280
+ s [OCELOT_STAT_RX_YELLOW_PRIO_6 ] +
281
+ s [OCELOT_STAT_RX_YELLOW_PRIO_7 ];
282
+ mac_stats -> MulticastFramesXmittedOK = s [OCELOT_STAT_TX_MULTICAST ];
283
+ mac_stats -> BroadcastFramesXmittedOK = s [OCELOT_STAT_TX_BROADCAST ];
284
+ mac_stats -> MulticastFramesReceivedOK = s [OCELOT_STAT_RX_MULTICAST ];
285
+ mac_stats -> BroadcastFramesReceivedOK = s [OCELOT_STAT_RX_BROADCAST ];
286
+ mac_stats -> FrameTooLongErrors = s [OCELOT_STAT_RX_LONGS ];
287
+ /* Sadly, C_RX_CRC is the sum of FCS and alignment errors, they are not
288
+ * counted individually.
289
+ */
290
+ mac_stats -> FrameCheckSequenceErrors = s [OCELOT_STAT_RX_CRC_ALIGN_ERRS ];
291
+ mac_stats -> AlignmentErrors = s [OCELOT_STAT_RX_CRC_ALIGN_ERRS ];
292
+ }
293
+
294
+ void ocelot_port_get_eth_mac_stats (struct ocelot * ocelot , int port ,
295
+ struct ethtool_eth_mac_stats * mac_stats )
296
+ {
297
+ ocelot_port_stats_run (ocelot , port , mac_stats ,
298
+ ocelot_port_mac_stats_cb );
299
+ }
300
+ EXPORT_SYMBOL_GPL (ocelot_port_get_eth_mac_stats );
301
+
302
+ static void ocelot_port_phy_stats_cb (struct ocelot * ocelot , int port , void * priv )
303
+ {
304
+ u64 * s = & ocelot -> stats [port * OCELOT_NUM_STATS ];
305
+ struct ethtool_eth_phy_stats * phy_stats = priv ;
306
+
307
+ phy_stats -> SymbolErrorDuringCarrier = s [OCELOT_STAT_RX_SYM_ERRS ];
308
+ }
309
+
310
+ void ocelot_port_get_eth_phy_stats (struct ocelot * ocelot , int port ,
311
+ struct ethtool_eth_phy_stats * phy_stats )
312
+ {
313
+ ocelot_port_stats_run (ocelot , port , phy_stats ,
314
+ ocelot_port_phy_stats_cb );
315
+ }
316
+ EXPORT_SYMBOL_GPL (ocelot_port_get_eth_phy_stats );
317
+
151
318
void ocelot_port_get_stats64 (struct ocelot * ocelot , int port ,
152
319
struct rtnl_link_stats64 * stats )
153
320
{
0 commit comments