278
278
279
279
#define MVNETA_RX_BUF_SIZE (pkt_size ) ((pkt_size) + NET_SKB_PAD)
280
280
281
+ struct mvneta_statistic {
282
+ unsigned short offset ;
283
+ unsigned short type ;
284
+ const char name [ETH_GSTRING_LEN ];
285
+ };
286
+
287
+ #define T_REG_32 32
288
+ #define T_REG_64 64
289
+
290
+ static const struct mvneta_statistic mvneta_statistics [] = {
291
+ { 0x3000 , T_REG_64 , "good_octets_received" , },
292
+ { 0x3010 , T_REG_32 , "good_frames_received" , },
293
+ { 0x3008 , T_REG_32 , "bad_octets_received" , },
294
+ { 0x3014 , T_REG_32 , "bad_frames_received" , },
295
+ { 0x3018 , T_REG_32 , "broadcast_frames_received" , },
296
+ { 0x301c , T_REG_32 , "multicast_frames_received" , },
297
+ { 0x3050 , T_REG_32 , "unrec_mac_control_received" , },
298
+ { 0x3058 , T_REG_32 , "good_fc_received" , },
299
+ { 0x305c , T_REG_32 , "bad_fc_received" , },
300
+ { 0x3060 , T_REG_32 , "undersize_received" , },
301
+ { 0x3064 , T_REG_32 , "fragments_received" , },
302
+ { 0x3068 , T_REG_32 , "oversize_received" , },
303
+ { 0x306c , T_REG_32 , "jabber_received" , },
304
+ { 0x3070 , T_REG_32 , "mac_receive_error" , },
305
+ { 0x3074 , T_REG_32 , "bad_crc_event" , },
306
+ { 0x3078 , T_REG_32 , "collision" , },
307
+ { 0x307c , T_REG_32 , "late_collision" , },
308
+ { 0x2484 , T_REG_32 , "rx_discard" , },
309
+ { 0x2488 , T_REG_32 , "rx_overrun" , },
310
+ { 0x3020 , T_REG_32 , "frames_64_octets" , },
311
+ { 0x3024 , T_REG_32 , "frames_65_to_127_octets" , },
312
+ { 0x3028 , T_REG_32 , "frames_128_to_255_octets" , },
313
+ { 0x302c , T_REG_32 , "frames_256_to_511_octets" , },
314
+ { 0x3030 , T_REG_32 , "frames_512_to_1023_octets" , },
315
+ { 0x3034 , T_REG_32 , "frames_1024_to_max_octets" , },
316
+ { 0x3038 , T_REG_64 , "good_octets_sent" , },
317
+ { 0x3040 , T_REG_32 , "good_frames_sent" , },
318
+ { 0x3044 , T_REG_32 , "excessive_collision" , },
319
+ { 0x3048 , T_REG_32 , "multicast_frames_sent" , },
320
+ { 0x304c , T_REG_32 , "broadcast_frames_sent" , },
321
+ { 0x3054 , T_REG_32 , "fc_sent" , },
322
+ { 0x300c , T_REG_32 , "internal_mac_transmit_err" , },
323
+ };
324
+
281
325
struct mvneta_pcpu_stats {
282
326
struct u64_stats_sync syncp ;
283
327
u64 rx_packets ;
@@ -324,6 +368,8 @@ struct mvneta_port {
324
368
unsigned int speed ;
325
369
unsigned int tx_csum_limit ;
326
370
int use_inband_status :1 ;
371
+
372
+ u64 ethtool_stats [ARRAY_SIZE (mvneta_statistics )];
327
373
};
328
374
329
375
/* The mvneta_tx_desc and mvneta_rx_desc structures describe the
@@ -2982,6 +3028,65 @@ static int mvneta_ethtool_set_ringparam(struct net_device *dev,
2982
3028
return 0 ;
2983
3029
}
2984
3030
3031
+ static void mvneta_ethtool_get_strings (struct net_device * netdev , u32 sset ,
3032
+ u8 * data )
3033
+ {
3034
+ if (sset == ETH_SS_STATS ) {
3035
+ int i ;
3036
+
3037
+ for (i = 0 ; i < ARRAY_SIZE (mvneta_statistics ); i ++ )
3038
+ memcpy (data + i * ETH_GSTRING_LEN ,
3039
+ mvneta_statistics [i ].name , ETH_GSTRING_LEN );
3040
+ }
3041
+ }
3042
+
3043
+ static void mvneta_ethtool_update_stats (struct mvneta_port * pp )
3044
+ {
3045
+ const struct mvneta_statistic * s ;
3046
+ void __iomem * base = pp -> base ;
3047
+ u32 high , low , val ;
3048
+ int i ;
3049
+
3050
+ for (i = 0 , s = mvneta_statistics ;
3051
+ s < mvneta_statistics + ARRAY_SIZE (mvneta_statistics );
3052
+ s ++ , i ++ ) {
3053
+ val = 0 ;
3054
+
3055
+ switch (s -> type ) {
3056
+ case T_REG_32 :
3057
+ val = readl_relaxed (base + s -> offset );
3058
+ break ;
3059
+ case T_REG_64 :
3060
+ /* Docs say to read low 32-bit then high */
3061
+ low = readl_relaxed (base + s -> offset );
3062
+ high = readl_relaxed (base + s -> offset + 4 );
3063
+ val = (u64 )high << 32 | low ;
3064
+ break ;
3065
+ }
3066
+
3067
+ pp -> ethtool_stats [i ] += val ;
3068
+ }
3069
+ }
3070
+
3071
+ static void mvneta_ethtool_get_stats (struct net_device * dev ,
3072
+ struct ethtool_stats * stats , u64 * data )
3073
+ {
3074
+ struct mvneta_port * pp = netdev_priv (dev );
3075
+ int i ;
3076
+
3077
+ mvneta_ethtool_update_stats (pp );
3078
+
3079
+ for (i = 0 ; i < ARRAY_SIZE (mvneta_statistics ); i ++ )
3080
+ * data ++ = pp -> ethtool_stats [i ];
3081
+ }
3082
+
3083
+ static int mvneta_ethtool_get_sset_count (struct net_device * dev , int sset )
3084
+ {
3085
+ if (sset == ETH_SS_STATS )
3086
+ return ARRAY_SIZE (mvneta_statistics );
3087
+ return - EOPNOTSUPP ;
3088
+ }
3089
+
2985
3090
static const struct net_device_ops mvneta_netdev_ops = {
2986
3091
.ndo_open = mvneta_open ,
2987
3092
.ndo_stop = mvneta_stop ,
@@ -3003,6 +3108,9 @@ const struct ethtool_ops mvneta_eth_tool_ops = {
3003
3108
.get_drvinfo = mvneta_ethtool_get_drvinfo ,
3004
3109
.get_ringparam = mvneta_ethtool_get_ringparam ,
3005
3110
.set_ringparam = mvneta_ethtool_set_ringparam ,
3111
+ .get_strings = mvneta_ethtool_get_strings ,
3112
+ .get_ethtool_stats = mvneta_ethtool_get_stats ,
3113
+ .get_sset_count = mvneta_ethtool_get_sset_count ,
3006
3114
};
3007
3115
3008
3116
/* Initialize hw */
0 commit comments