Skip to content

Commit 9b0cdef

Browse files
Russell Kingdavem330
authored andcommitted
net: mvneta: add ethtool statistics
Add support for the ethtool statistic interface, returning the full set of statistics which both Armada 370, 38x and Armada XP can support. Tested-by: Andrew Lunn <[email protected]> Signed-off-by: Russell King <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 1586a58 commit 9b0cdef

File tree

1 file changed

+108
-0
lines changed

1 file changed

+108
-0
lines changed

drivers/net/ethernet/marvell/mvneta.c

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,50 @@
278278

279279
#define MVNETA_RX_BUF_SIZE(pkt_size) ((pkt_size) + NET_SKB_PAD)
280280

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+
281325
struct mvneta_pcpu_stats {
282326
struct u64_stats_sync syncp;
283327
u64 rx_packets;
@@ -324,6 +368,8 @@ struct mvneta_port {
324368
unsigned int speed;
325369
unsigned int tx_csum_limit;
326370
int use_inband_status:1;
371+
372+
u64 ethtool_stats[ARRAY_SIZE(mvneta_statistics)];
327373
};
328374

329375
/* 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,
29823028
return 0;
29833029
}
29843030

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+
29853090
static const struct net_device_ops mvneta_netdev_ops = {
29863091
.ndo_open = mvneta_open,
29873092
.ndo_stop = mvneta_stop,
@@ -3003,6 +3108,9 @@ const struct ethtool_ops mvneta_eth_tool_ops = {
30033108
.get_drvinfo = mvneta_ethtool_get_drvinfo,
30043109
.get_ringparam = mvneta_ethtool_get_ringparam,
30053110
.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,
30063114
};
30073115

30083116
/* Initialize hw */

0 commit comments

Comments
 (0)