Skip to content

Commit da92bf9

Browse files
committed
Merge branch 'mvneta-ethtool-stats'
Russell King says: ==================== mvneta ethtool statistics Sorry for v3 - I forgot to update the commit message on patch 1 as requested by Marcin. This short series adds ethtool statistics reporting to mvneta. Having discussed with Andrew on IRC, we decided I'd pick up his patch into my series. My change for patch 1 compared to the previous RFC splits out the reading of the statistics from the hardware into a separate function, in order to facilitate work going on elsewhere to arrange for the statistics to be preserved across a suspend/resume cycle. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 1586a58 + e483911 commit da92bf9

File tree

1 file changed

+115
-2
lines changed

1 file changed

+115
-2
lines changed

drivers/net/ethernet/marvell/mvneta.c

Lines changed: 115 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@
101101
#define MVNETA_TXQ_CMD 0x2448
102102
#define MVNETA_TXQ_DISABLE_SHIFT 8
103103
#define MVNETA_TXQ_ENABLE_MASK 0x000000ff
104+
#define MVNETA_RX_DISCARD_FRAME_COUNT 0x2484
105+
#define MVNETA_OVERRUN_FRAME_COUNT 0x2488
104106
#define MVNETA_GMAC_CLOCK_DIVIDER 0x24f4
105107
#define MVNETA_GMAC_1MS_CLOCK_ENABLE BIT(31)
106108
#define MVNETA_ACC_MODE 0x2500
@@ -192,7 +194,7 @@
192194
#define MVNETA_GMAC_AN_FLOW_CTRL_EN BIT(11)
193195
#define MVNETA_GMAC_CONFIG_FULL_DUPLEX BIT(12)
194196
#define MVNETA_GMAC_AN_DUPLEX_EN BIT(13)
195-
#define MVNETA_MIB_COUNTERS_BASE 0x3080
197+
#define MVNETA_MIB_COUNTERS_BASE 0x3000
196198
#define MVNETA_MIB_LATE_COLLISION 0x7c
197199
#define MVNETA_DA_FILT_SPEC_MCAST 0x3400
198200
#define MVNETA_DA_FILT_OTH_MCAST 0x3500
@@ -278,6 +280,50 @@
278280

279281
#define MVNETA_RX_BUF_SIZE(pkt_size) ((pkt_size) + NET_SKB_PAD)
280282

283+
struct mvneta_statistic {
284+
unsigned short offset;
285+
unsigned short type;
286+
const char name[ETH_GSTRING_LEN];
287+
};
288+
289+
#define T_REG_32 32
290+
#define T_REG_64 64
291+
292+
static const struct mvneta_statistic mvneta_statistics[] = {
293+
{ 0x3000, T_REG_64, "good_octets_received", },
294+
{ 0x3010, T_REG_32, "good_frames_received", },
295+
{ 0x3008, T_REG_32, "bad_octets_received", },
296+
{ 0x3014, T_REG_32, "bad_frames_received", },
297+
{ 0x3018, T_REG_32, "broadcast_frames_received", },
298+
{ 0x301c, T_REG_32, "multicast_frames_received", },
299+
{ 0x3050, T_REG_32, "unrec_mac_control_received", },
300+
{ 0x3058, T_REG_32, "good_fc_received", },
301+
{ 0x305c, T_REG_32, "bad_fc_received", },
302+
{ 0x3060, T_REG_32, "undersize_received", },
303+
{ 0x3064, T_REG_32, "fragments_received", },
304+
{ 0x3068, T_REG_32, "oversize_received", },
305+
{ 0x306c, T_REG_32, "jabber_received", },
306+
{ 0x3070, T_REG_32, "mac_receive_error", },
307+
{ 0x3074, T_REG_32, "bad_crc_event", },
308+
{ 0x3078, T_REG_32, "collision", },
309+
{ 0x307c, T_REG_32, "late_collision", },
310+
{ 0x2484, T_REG_32, "rx_discard", },
311+
{ 0x2488, T_REG_32, "rx_overrun", },
312+
{ 0x3020, T_REG_32, "frames_64_octets", },
313+
{ 0x3024, T_REG_32, "frames_65_to_127_octets", },
314+
{ 0x3028, T_REG_32, "frames_128_to_255_octets", },
315+
{ 0x302c, T_REG_32, "frames_256_to_511_octets", },
316+
{ 0x3030, T_REG_32, "frames_512_to_1023_octets", },
317+
{ 0x3034, T_REG_32, "frames_1024_to_max_octets", },
318+
{ 0x3038, T_REG_64, "good_octets_sent", },
319+
{ 0x3040, T_REG_32, "good_frames_sent", },
320+
{ 0x3044, T_REG_32, "excessive_collision", },
321+
{ 0x3048, T_REG_32, "multicast_frames_sent", },
322+
{ 0x304c, T_REG_32, "broadcast_frames_sent", },
323+
{ 0x3054, T_REG_32, "fc_sent", },
324+
{ 0x300c, T_REG_32, "internal_mac_transmit_err", },
325+
};
326+
281327
struct mvneta_pcpu_stats {
282328
struct u64_stats_sync syncp;
283329
u64 rx_packets;
@@ -324,6 +370,8 @@ struct mvneta_port {
324370
unsigned int speed;
325371
unsigned int tx_csum_limit;
326372
int use_inband_status:1;
373+
374+
u64 ethtool_stats[ARRAY_SIZE(mvneta_statistics)];
327375
};
328376

329377
/* The mvneta_tx_desc and mvneta_rx_desc structures describe the
@@ -530,6 +578,8 @@ static void mvneta_mib_counters_clear(struct mvneta_port *pp)
530578
/* Perform dummy reads from MIB counters */
531579
for (i = 0; i < MVNETA_MIB_LATE_COLLISION; i += 4)
532580
dummy = mvreg_read(pp, (MVNETA_MIB_COUNTERS_BASE + i));
581+
dummy = mvreg_read(pp, MVNETA_RX_DISCARD_FRAME_COUNT);
582+
dummy = mvreg_read(pp, MVNETA_OVERRUN_FRAME_COUNT);
533583
}
534584

535585
/* Get System Network Statistics */
@@ -758,7 +808,6 @@ static void mvneta_port_up(struct mvneta_port *pp)
758808
u32 q_map;
759809

760810
/* Enable all initialized TXs. */
761-
mvneta_mib_counters_clear(pp);
762811
q_map = 0;
763812
for (queue = 0; queue < txq_number; queue++) {
764813
struct mvneta_tx_queue *txq = &pp->txqs[queue];
@@ -1035,6 +1084,8 @@ static void mvneta_defaults_set(struct mvneta_port *pp)
10351084
mvreg_write(pp, MVNETA_INTR_ENABLE,
10361085
(MVNETA_RXQ_INTR_ENABLE_ALL_MASK
10371086
| MVNETA_TXQ_INTR_ENABLE_ALL_MASK));
1087+
1088+
mvneta_mib_counters_clear(pp);
10381089
}
10391090

10401091
/* Set max sizes for tx queues */
@@ -2982,6 +3033,65 @@ static int mvneta_ethtool_set_ringparam(struct net_device *dev,
29823033
return 0;
29833034
}
29843035

3036+
static void mvneta_ethtool_get_strings(struct net_device *netdev, u32 sset,
3037+
u8 *data)
3038+
{
3039+
if (sset == ETH_SS_STATS) {
3040+
int i;
3041+
3042+
for (i = 0; i < ARRAY_SIZE(mvneta_statistics); i++)
3043+
memcpy(data + i * ETH_GSTRING_LEN,
3044+
mvneta_statistics[i].name, ETH_GSTRING_LEN);
3045+
}
3046+
}
3047+
3048+
static void mvneta_ethtool_update_stats(struct mvneta_port *pp)
3049+
{
3050+
const struct mvneta_statistic *s;
3051+
void __iomem *base = pp->base;
3052+
u32 high, low, val;
3053+
int i;
3054+
3055+
for (i = 0, s = mvneta_statistics;
3056+
s < mvneta_statistics + ARRAY_SIZE(mvneta_statistics);
3057+
s++, i++) {
3058+
val = 0;
3059+
3060+
switch (s->type) {
3061+
case T_REG_32:
3062+
val = readl_relaxed(base + s->offset);
3063+
break;
3064+
case T_REG_64:
3065+
/* Docs say to read low 32-bit then high */
3066+
low = readl_relaxed(base + s->offset);
3067+
high = readl_relaxed(base + s->offset + 4);
3068+
val = (u64)high << 32 | low;
3069+
break;
3070+
}
3071+
3072+
pp->ethtool_stats[i] += val;
3073+
}
3074+
}
3075+
3076+
static void mvneta_ethtool_get_stats(struct net_device *dev,
3077+
struct ethtool_stats *stats, u64 *data)
3078+
{
3079+
struct mvneta_port *pp = netdev_priv(dev);
3080+
int i;
3081+
3082+
mvneta_ethtool_update_stats(pp);
3083+
3084+
for (i = 0; i < ARRAY_SIZE(mvneta_statistics); i++)
3085+
*data++ = pp->ethtool_stats[i];
3086+
}
3087+
3088+
static int mvneta_ethtool_get_sset_count(struct net_device *dev, int sset)
3089+
{
3090+
if (sset == ETH_SS_STATS)
3091+
return ARRAY_SIZE(mvneta_statistics);
3092+
return -EOPNOTSUPP;
3093+
}
3094+
29853095
static const struct net_device_ops mvneta_netdev_ops = {
29863096
.ndo_open = mvneta_open,
29873097
.ndo_stop = mvneta_stop,
@@ -3003,6 +3113,9 @@ const struct ethtool_ops mvneta_eth_tool_ops = {
30033113
.get_drvinfo = mvneta_ethtool_get_drvinfo,
30043114
.get_ringparam = mvneta_ethtool_get_ringparam,
30053115
.set_ringparam = mvneta_ethtool_set_ringparam,
3116+
.get_strings = mvneta_ethtool_get_strings,
3117+
.get_ethtool_stats = mvneta_ethtool_get_stats,
3118+
.get_sset_count = mvneta_ethtool_get_sset_count,
30063119
};
30073120

30083121
/* Initialize hw */

0 commit comments

Comments
 (0)