Commit b84d66b0 authored by David S. Miller's avatar David S. Miller

Merge branch 'mv88e6xxx-counters'

Tobias Waldekranz says:

====================
net: dsa: mv88e6xxx: Add "eth-mac" and "rmon" counter group support

The majority of the changes (2/8) are about refactoring the existing
ethtool statistics support to make it possible to read individual
counters, rather than the whole set.

4/8 tries to collect all information about a stat in a single place
using a mapper macro, which is then used to generate the original list
of stats, along with a matching enum. checkpatch is less than amused
with this construct, but prior art exists (__BPF_FUNC_MAPPER in
include/uapi/linux/bpf.h, for example).

To support the histogram counters from the "rmon" group, we have to
change mv88e6xxx's configuration of them. Instead of counting rx and
tx, we restrict them to rx-only. 6/8 has the details.

With that in place, adding the actual counter groups is pretty
straight forward (5,7/8).

Tie it all together with a selftest (8/8).

v3 -> v4:
- Return size_t from mv88e6xxx_stats_get_stats
- Spelling errors in commit message of 6/8
- Improve selftest:
  - Report progress per-bucket
  - Test both ports in the pair
  - Increase MTU, if required

v2 -> v3:
- Added 6/8
- Added 8/8

v1 -> v2:
- Added 1/6
- Added 3/6
- Changed prototype of stats operation to reflect the fact that the
  number of read stats are returned, no errors
- Moved comma into MV88E6XXX_HW_STAT_MAPPER definition
- Avoid the construction of mapping table iteration which relied on
  struct layouts outside of mv88e6xxx's control
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 9ed816b1 00e7f29d
......@@ -943,76 +943,94 @@ static void mv88e6xxx_mac_link_up(struct dsa_switch *ds, int port,
static int mv88e6xxx_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
{
int err;
if (!chip->info->ops->stats_snapshot)
return -EOPNOTSUPP;
return chip->info->ops->stats_snapshot(chip, port);
}
static struct mv88e6xxx_hw_stat mv88e6xxx_hw_stats[] = {
{ "in_good_octets", 8, 0x00, STATS_TYPE_BANK0, },
{ "in_bad_octets", 4, 0x02, STATS_TYPE_BANK0, },
{ "in_unicast", 4, 0x04, STATS_TYPE_BANK0, },
{ "in_broadcasts", 4, 0x06, STATS_TYPE_BANK0, },
{ "in_multicasts", 4, 0x07, STATS_TYPE_BANK0, },
{ "in_pause", 4, 0x16, STATS_TYPE_BANK0, },
{ "in_undersize", 4, 0x18, STATS_TYPE_BANK0, },
{ "in_fragments", 4, 0x19, STATS_TYPE_BANK0, },
{ "in_oversize", 4, 0x1a, STATS_TYPE_BANK0, },
{ "in_jabber", 4, 0x1b, STATS_TYPE_BANK0, },
{ "in_rx_error", 4, 0x1c, STATS_TYPE_BANK0, },
{ "in_fcs_error", 4, 0x1d, STATS_TYPE_BANK0, },
{ "out_octets", 8, 0x0e, STATS_TYPE_BANK0, },
{ "out_unicast", 4, 0x10, STATS_TYPE_BANK0, },
{ "out_broadcasts", 4, 0x13, STATS_TYPE_BANK0, },
{ "out_multicasts", 4, 0x12, STATS_TYPE_BANK0, },
{ "out_pause", 4, 0x15, STATS_TYPE_BANK0, },
{ "excessive", 4, 0x11, STATS_TYPE_BANK0, },
{ "collisions", 4, 0x1e, STATS_TYPE_BANK0, },
{ "deferred", 4, 0x05, STATS_TYPE_BANK0, },
{ "single", 4, 0x14, STATS_TYPE_BANK0, },
{ "multiple", 4, 0x17, STATS_TYPE_BANK0, },
{ "out_fcs_error", 4, 0x03, STATS_TYPE_BANK0, },
{ "late", 4, 0x1f, STATS_TYPE_BANK0, },
{ "hist_64bytes", 4, 0x08, STATS_TYPE_BANK0, },
{ "hist_65_127bytes", 4, 0x09, STATS_TYPE_BANK0, },
{ "hist_128_255bytes", 4, 0x0a, STATS_TYPE_BANK0, },
{ "hist_256_511bytes", 4, 0x0b, STATS_TYPE_BANK0, },
{ "hist_512_1023bytes", 4, 0x0c, STATS_TYPE_BANK0, },
{ "hist_1024_max_bytes", 4, 0x0d, STATS_TYPE_BANK0, },
{ "sw_in_discards", 4, 0x10, STATS_TYPE_PORT, },
{ "sw_in_filtered", 2, 0x12, STATS_TYPE_PORT, },
{ "sw_out_filtered", 2, 0x13, STATS_TYPE_PORT, },
{ "in_discards", 4, 0x00, STATS_TYPE_BANK1, },
{ "in_filtered", 4, 0x01, STATS_TYPE_BANK1, },
{ "in_accepted", 4, 0x02, STATS_TYPE_BANK1, },
{ "in_bad_accepted", 4, 0x03, STATS_TYPE_BANK1, },
{ "in_good_avb_class_a", 4, 0x04, STATS_TYPE_BANK1, },
{ "in_good_avb_class_b", 4, 0x05, STATS_TYPE_BANK1, },
{ "in_bad_avb_class_a", 4, 0x06, STATS_TYPE_BANK1, },
{ "in_bad_avb_class_b", 4, 0x07, STATS_TYPE_BANK1, },
{ "tcam_counter_0", 4, 0x08, STATS_TYPE_BANK1, },
{ "tcam_counter_1", 4, 0x09, STATS_TYPE_BANK1, },
{ "tcam_counter_2", 4, 0x0a, STATS_TYPE_BANK1, },
{ "tcam_counter_3", 4, 0x0b, STATS_TYPE_BANK1, },
{ "in_da_unknown", 4, 0x0e, STATS_TYPE_BANK1, },
{ "in_management", 4, 0x0f, STATS_TYPE_BANK1, },
{ "out_queue_0", 4, 0x10, STATS_TYPE_BANK1, },
{ "out_queue_1", 4, 0x11, STATS_TYPE_BANK1, },
{ "out_queue_2", 4, 0x12, STATS_TYPE_BANK1, },
{ "out_queue_3", 4, 0x13, STATS_TYPE_BANK1, },
{ "out_queue_4", 4, 0x14, STATS_TYPE_BANK1, },
{ "out_queue_5", 4, 0x15, STATS_TYPE_BANK1, },
{ "out_queue_6", 4, 0x16, STATS_TYPE_BANK1, },
{ "out_queue_7", 4, 0x17, STATS_TYPE_BANK1, },
{ "out_cut_through", 4, 0x18, STATS_TYPE_BANK1, },
{ "out_octets_a", 4, 0x1a, STATS_TYPE_BANK1, },
{ "out_octets_b", 4, 0x1b, STATS_TYPE_BANK1, },
{ "out_management", 4, 0x1f, STATS_TYPE_BANK1, },
mv88e6xxx_reg_lock(chip);
err = chip->info->ops->stats_snapshot(chip, port);
mv88e6xxx_reg_unlock(chip);
return err;
}
#define MV88E6XXX_HW_STAT_MAPPER(_fn) \
_fn(in_good_octets, 8, 0x00, STATS_TYPE_BANK0), \
_fn(in_bad_octets, 4, 0x02, STATS_TYPE_BANK0), \
_fn(in_unicast, 4, 0x04, STATS_TYPE_BANK0), \
_fn(in_broadcasts, 4, 0x06, STATS_TYPE_BANK0), \
_fn(in_multicasts, 4, 0x07, STATS_TYPE_BANK0), \
_fn(in_pause, 4, 0x16, STATS_TYPE_BANK0), \
_fn(in_undersize, 4, 0x18, STATS_TYPE_BANK0), \
_fn(in_fragments, 4, 0x19, STATS_TYPE_BANK0), \
_fn(in_oversize, 4, 0x1a, STATS_TYPE_BANK0), \
_fn(in_jabber, 4, 0x1b, STATS_TYPE_BANK0), \
_fn(in_rx_error, 4, 0x1c, STATS_TYPE_BANK0), \
_fn(in_fcs_error, 4, 0x1d, STATS_TYPE_BANK0), \
_fn(out_octets, 8, 0x0e, STATS_TYPE_BANK0), \
_fn(out_unicast, 4, 0x10, STATS_TYPE_BANK0), \
_fn(out_broadcasts, 4, 0x13, STATS_TYPE_BANK0), \
_fn(out_multicasts, 4, 0x12, STATS_TYPE_BANK0), \
_fn(out_pause, 4, 0x15, STATS_TYPE_BANK0), \
_fn(excessive, 4, 0x11, STATS_TYPE_BANK0), \
_fn(collisions, 4, 0x1e, STATS_TYPE_BANK0), \
_fn(deferred, 4, 0x05, STATS_TYPE_BANK0), \
_fn(single, 4, 0x14, STATS_TYPE_BANK0), \
_fn(multiple, 4, 0x17, STATS_TYPE_BANK0), \
_fn(out_fcs_error, 4, 0x03, STATS_TYPE_BANK0), \
_fn(late, 4, 0x1f, STATS_TYPE_BANK0), \
_fn(hist_64bytes, 4, 0x08, STATS_TYPE_BANK0), \
_fn(hist_65_127bytes, 4, 0x09, STATS_TYPE_BANK0), \
_fn(hist_128_255bytes, 4, 0x0a, STATS_TYPE_BANK0), \
_fn(hist_256_511bytes, 4, 0x0b, STATS_TYPE_BANK0), \
_fn(hist_512_1023bytes, 4, 0x0c, STATS_TYPE_BANK0), \
_fn(hist_1024_max_bytes, 4, 0x0d, STATS_TYPE_BANK0), \
_fn(sw_in_discards, 4, 0x10, STATS_TYPE_PORT), \
_fn(sw_in_filtered, 2, 0x12, STATS_TYPE_PORT), \
_fn(sw_out_filtered, 2, 0x13, STATS_TYPE_PORT), \
_fn(in_discards, 4, 0x00, STATS_TYPE_BANK1), \
_fn(in_filtered, 4, 0x01, STATS_TYPE_BANK1), \
_fn(in_accepted, 4, 0x02, STATS_TYPE_BANK1), \
_fn(in_bad_accepted, 4, 0x03, STATS_TYPE_BANK1), \
_fn(in_good_avb_class_a, 4, 0x04, STATS_TYPE_BANK1), \
_fn(in_good_avb_class_b, 4, 0x05, STATS_TYPE_BANK1), \
_fn(in_bad_avb_class_a, 4, 0x06, STATS_TYPE_BANK1), \
_fn(in_bad_avb_class_b, 4, 0x07, STATS_TYPE_BANK1), \
_fn(tcam_counter_0, 4, 0x08, STATS_TYPE_BANK1), \
_fn(tcam_counter_1, 4, 0x09, STATS_TYPE_BANK1), \
_fn(tcam_counter_2, 4, 0x0a, STATS_TYPE_BANK1), \
_fn(tcam_counter_3, 4, 0x0b, STATS_TYPE_BANK1), \
_fn(in_da_unknown, 4, 0x0e, STATS_TYPE_BANK1), \
_fn(in_management, 4, 0x0f, STATS_TYPE_BANK1), \
_fn(out_queue_0, 4, 0x10, STATS_TYPE_BANK1), \
_fn(out_queue_1, 4, 0x11, STATS_TYPE_BANK1), \
_fn(out_queue_2, 4, 0x12, STATS_TYPE_BANK1), \
_fn(out_queue_3, 4, 0x13, STATS_TYPE_BANK1), \
_fn(out_queue_4, 4, 0x14, STATS_TYPE_BANK1), \
_fn(out_queue_5, 4, 0x15, STATS_TYPE_BANK1), \
_fn(out_queue_6, 4, 0x16, STATS_TYPE_BANK1), \
_fn(out_queue_7, 4, 0x17, STATS_TYPE_BANK1), \
_fn(out_cut_through, 4, 0x18, STATS_TYPE_BANK1), \
_fn(out_octets_a, 4, 0x1a, STATS_TYPE_BANK1), \
_fn(out_octets_b, 4, 0x1b, STATS_TYPE_BANK1), \
_fn(out_management, 4, 0x1f, STATS_TYPE_BANK1), \
/* */
#define MV88E6XXX_HW_STAT_ENTRY(_string, _size, _reg, _type) \
{ #_string, _size, _reg, _type }
static const struct mv88e6xxx_hw_stat mv88e6xxx_hw_stats[] = {
MV88E6XXX_HW_STAT_MAPPER(MV88E6XXX_HW_STAT_ENTRY)
};
#define MV88E6XXX_HW_STAT_ENUM(_string, _size, _reg, _type) \
MV88E6XXX_HW_STAT_ID_ ## _string
enum mv88e6xxx_hw_stat_id {
MV88E6XXX_HW_STAT_MAPPER(MV88E6XXX_HW_STAT_ENUM)
};
static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip,
struct mv88e6xxx_hw_stat *s,
const struct mv88e6xxx_hw_stat *s,
int port, u16 bank1_select,
u16 histogram)
{
......@@ -1055,7 +1073,7 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip,
static int mv88e6xxx_stats_get_strings(struct mv88e6xxx_chip *chip,
uint8_t *data, int types)
{
struct mv88e6xxx_hw_stat *stat;
const struct mv88e6xxx_hw_stat *stat;
int i, j;
for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
......@@ -1136,7 +1154,7 @@ static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port,
static int mv88e6xxx_stats_get_sset_count(struct mv88e6xxx_chip *chip,
int types)
{
struct mv88e6xxx_hw_stat *stat;
const struct mv88e6xxx_hw_stat *stat;
int i, j;
for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
......@@ -1195,59 +1213,82 @@ static int mv88e6xxx_get_sset_count(struct dsa_switch *ds, int port, int sset)
return count;
}
static int mv88e6xxx_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
uint64_t *data, int types,
u16 bank1_select, u16 histogram)
static size_t mv88e6095_stats_get_stat(struct mv88e6xxx_chip *chip, int port,
const struct mv88e6xxx_hw_stat *stat,
uint64_t *data)
{
struct mv88e6xxx_hw_stat *stat;
int i, j;
if (!(stat->type & (STATS_TYPE_BANK0 | STATS_TYPE_PORT)))
return 0;
for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
stat = &mv88e6xxx_hw_stats[i];
if (stat->type & types) {
mv88e6xxx_reg_lock(chip);
data[j] = _mv88e6xxx_get_ethtool_stat(chip, stat, port,
bank1_select,
histogram);
mv88e6xxx_reg_unlock(chip);
*data = _mv88e6xxx_get_ethtool_stat(chip, stat, port, 0,
MV88E6XXX_G1_STATS_OP_HIST_RX);
return 1;
}
j++;
}
}
return j;
static size_t mv88e6250_stats_get_stat(struct mv88e6xxx_chip *chip, int port,
const struct mv88e6xxx_hw_stat *stat,
uint64_t *data)
{
if (!(stat->type & STATS_TYPE_BANK0))
return 0;
*data = _mv88e6xxx_get_ethtool_stat(chip, stat, port, 0,
MV88E6XXX_G1_STATS_OP_HIST_RX);
return 1;
}
static int mv88e6095_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
uint64_t *data)
static size_t mv88e6320_stats_get_stat(struct mv88e6xxx_chip *chip, int port,
const struct mv88e6xxx_hw_stat *stat,
uint64_t *data)
{
return mv88e6xxx_stats_get_stats(chip, port, data,
STATS_TYPE_BANK0 | STATS_TYPE_PORT,
0, MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
if (!(stat->type & (STATS_TYPE_BANK0 | STATS_TYPE_BANK1)))
return 0;
*data = _mv88e6xxx_get_ethtool_stat(chip, stat, port,
MV88E6XXX_G1_STATS_OP_BANK_1_BIT_9,
MV88E6XXX_G1_STATS_OP_HIST_RX);
return 1;
}
static int mv88e6250_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
uint64_t *data)
static size_t mv88e6390_stats_get_stat(struct mv88e6xxx_chip *chip, int port,
const struct mv88e6xxx_hw_stat *stat,
uint64_t *data)
{
return mv88e6xxx_stats_get_stats(chip, port, data, STATS_TYPE_BANK0,
0, MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
if (!(stat->type & (STATS_TYPE_BANK0 | STATS_TYPE_BANK1)))
return 0;
*data = _mv88e6xxx_get_ethtool_stat(chip, stat, port,
MV88E6XXX_G1_STATS_OP_BANK_1_BIT_10,
0);
return 1;
}
static int mv88e6320_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
uint64_t *data)
static size_t mv88e6xxx_stats_get_stat(struct mv88e6xxx_chip *chip, int port,
const struct mv88e6xxx_hw_stat *stat,
uint64_t *data)
{
return mv88e6xxx_stats_get_stats(chip, port, data,
STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
MV88E6XXX_G1_STATS_OP_BANK_1_BIT_9,
MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
int ret = 0;
if (chip->info->ops->stats_get_stat) {
mv88e6xxx_reg_lock(chip);
ret = chip->info->ops->stats_get_stat(chip, port, stat, data);
mv88e6xxx_reg_unlock(chip);
}
return ret;
}
static int mv88e6390_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
uint64_t *data)
static size_t mv88e6xxx_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
uint64_t *data)
{
return mv88e6xxx_stats_get_stats(chip, port, data,
STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
MV88E6XXX_G1_STATS_OP_BANK_1_BIT_10,
0);
const struct mv88e6xxx_hw_stat *stat;
size_t i, j;
for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
stat = &mv88e6xxx_hw_stats[i];
j += mv88e6xxx_stats_get_stat(chip, port, stat, &data[j]);
}
return j;
}
static void mv88e6xxx_atu_vtu_get_stats(struct mv88e6xxx_chip *chip, int port,
......@@ -1263,10 +1304,9 @@ static void mv88e6xxx_atu_vtu_get_stats(struct mv88e6xxx_chip *chip, int port,
static void mv88e6xxx_get_stats(struct mv88e6xxx_chip *chip, int port,
uint64_t *data)
{
int count = 0;
size_t count;
if (chip->info->ops->stats_get_stats)
count = chip->info->ops->stats_get_stats(chip, port, data);
count = mv88e6xxx_stats_get_stats(chip, port, data);
mv88e6xxx_reg_lock(chip);
if (chip->info->ops->serdes_get_stats) {
......@@ -1284,16 +1324,90 @@ static void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
struct mv88e6xxx_chip *chip = ds->priv;
int ret;
mv88e6xxx_reg_lock(chip);
ret = mv88e6xxx_stats_snapshot(chip, port);
if (ret < 0)
return;
mv88e6xxx_get_stats(chip, port, data);
}
static void mv88e6xxx_get_eth_mac_stats(struct dsa_switch *ds, int port,
struct ethtool_eth_mac_stats *mac_stats)
{
struct mv88e6xxx_chip *chip = ds->priv;
int ret;
ret = mv88e6xxx_stats_snapshot(chip, port);
mv88e6xxx_reg_unlock(chip);
if (ret < 0)
return;
#define MV88E6XXX_ETH_MAC_STAT_MAP(_id, _member) \
mv88e6xxx_stats_get_stat(chip, port, \
&mv88e6xxx_hw_stats[MV88E6XXX_HW_STAT_ID_ ## _id], \
&mac_stats->stats._member)
MV88E6XXX_ETH_MAC_STAT_MAP(out_unicast, FramesTransmittedOK);
MV88E6XXX_ETH_MAC_STAT_MAP(single, SingleCollisionFrames);
MV88E6XXX_ETH_MAC_STAT_MAP(multiple, MultipleCollisionFrames);
MV88E6XXX_ETH_MAC_STAT_MAP(in_unicast, FramesReceivedOK);
MV88E6XXX_ETH_MAC_STAT_MAP(in_fcs_error, FrameCheckSequenceErrors);
MV88E6XXX_ETH_MAC_STAT_MAP(out_octets, OctetsTransmittedOK);
MV88E6XXX_ETH_MAC_STAT_MAP(deferred, FramesWithDeferredXmissions);
MV88E6XXX_ETH_MAC_STAT_MAP(late, LateCollisions);
MV88E6XXX_ETH_MAC_STAT_MAP(in_good_octets, OctetsReceivedOK);
MV88E6XXX_ETH_MAC_STAT_MAP(out_multicasts, MulticastFramesXmittedOK);
MV88E6XXX_ETH_MAC_STAT_MAP(out_broadcasts, BroadcastFramesXmittedOK);
MV88E6XXX_ETH_MAC_STAT_MAP(excessive, FramesWithExcessiveDeferral);
MV88E6XXX_ETH_MAC_STAT_MAP(in_multicasts, MulticastFramesReceivedOK);
MV88E6XXX_ETH_MAC_STAT_MAP(in_broadcasts, BroadcastFramesReceivedOK);
#undef MV88E6XXX_ETH_MAC_STAT_MAP
mac_stats->stats.FramesTransmittedOK += mac_stats->stats.MulticastFramesXmittedOK;
mac_stats->stats.FramesTransmittedOK += mac_stats->stats.BroadcastFramesXmittedOK;
mac_stats->stats.FramesReceivedOK += mac_stats->stats.MulticastFramesReceivedOK;
mac_stats->stats.FramesReceivedOK += mac_stats->stats.BroadcastFramesReceivedOK;
}
static void mv88e6xxx_get_rmon_stats(struct dsa_switch *ds, int port,
struct ethtool_rmon_stats *rmon_stats,
const struct ethtool_rmon_hist_range **ranges)
{
static const struct ethtool_rmon_hist_range rmon_ranges[] = {
{ 64, 64 },
{ 65, 127 },
{ 128, 255 },
{ 256, 511 },
{ 512, 1023 },
{ 1024, 65535 },
{}
};
struct mv88e6xxx_chip *chip = ds->priv;
int ret;
ret = mv88e6xxx_stats_snapshot(chip, port);
if (ret < 0)
return;
mv88e6xxx_get_stats(chip, port, data);
#define MV88E6XXX_RMON_STAT_MAP(_id, _member) \
mv88e6xxx_stats_get_stat(chip, port, \
&mv88e6xxx_hw_stats[MV88E6XXX_HW_STAT_ID_ ## _id], \
&rmon_stats->stats._member)
MV88E6XXX_RMON_STAT_MAP(in_undersize, undersize_pkts);
MV88E6XXX_RMON_STAT_MAP(in_oversize, oversize_pkts);
MV88E6XXX_RMON_STAT_MAP(in_fragments, fragments);
MV88E6XXX_RMON_STAT_MAP(in_jabber, jabbers);
MV88E6XXX_RMON_STAT_MAP(hist_64bytes, hist[0]);
MV88E6XXX_RMON_STAT_MAP(hist_65_127bytes, hist[1]);
MV88E6XXX_RMON_STAT_MAP(hist_128_255bytes, hist[2]);
MV88E6XXX_RMON_STAT_MAP(hist_256_511bytes, hist[3]);
MV88E6XXX_RMON_STAT_MAP(hist_512_1023bytes, hist[4]);
MV88E6XXX_RMON_STAT_MAP(hist_1024_max_bytes, hist[5]);
#undef MV88E6XXX_RMON_STAT_MAP
*ranges = rmon_ranges;
}
static int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port)
......@@ -3987,7 +4101,7 @@ static const struct mv88e6xxx_ops mv88e6085_ops = {
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
.stats_get_strings = mv88e6095_stats_get_strings,
.stats_get_stats = mv88e6095_stats_get_stats,
.stats_get_stat = mv88e6095_stats_get_stat,
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6097_watchdog_ops,
......@@ -4025,7 +4139,7 @@ static const struct mv88e6xxx_ops mv88e6095_ops = {
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
.stats_get_strings = mv88e6095_stats_get_strings,
.stats_get_stats = mv88e6095_stats_get_stats,
.stats_get_stat = mv88e6095_stats_get_stat,
.mgmt_rsvd2cpu = mv88e6185_g2_mgmt_rsvd2cpu,
.ppu_enable = mv88e6185_g1_ppu_enable,
.ppu_disable = mv88e6185_g1_ppu_disable,
......@@ -4066,7 +4180,7 @@ static const struct mv88e6xxx_ops mv88e6097_ops = {
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
.stats_get_strings = mv88e6095_stats_get_strings,
.stats_get_stats = mv88e6095_stats_get_stats,
.stats_get_stat = mv88e6095_stats_get_stat,
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6097_watchdog_ops,
......@@ -4108,7 +4222,7 @@ static const struct mv88e6xxx_ops mv88e6123_ops = {
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
.stats_get_strings = mv88e6095_stats_get_strings,
.stats_get_stats = mv88e6095_stats_get_stats,
.stats_get_stat = mv88e6095_stats_get_stat,
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6097_watchdog_ops,
......@@ -4151,7 +4265,7 @@ static const struct mv88e6xxx_ops mv88e6131_ops = {
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
.stats_get_strings = mv88e6095_stats_get_strings,
.stats_get_stats = mv88e6095_stats_get_stats,
.stats_get_stat = mv88e6095_stats_get_stat,
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6097_watchdog_ops,
......@@ -4200,7 +4314,7 @@ static const struct mv88e6xxx_ops mv88e6141_ops = {
.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
.stats_get_strings = mv88e6320_stats_get_strings,
.stats_get_stats = mv88e6390_stats_get_stats,
.stats_get_stat = mv88e6390_stats_get_stat,
.set_cpu_port = mv88e6390_g1_set_cpu_port,
.set_egress_port = mv88e6390_g1_set_egress_port,
.watchdog_ops = &mv88e6390_watchdog_ops,
......@@ -4255,7 +4369,7 @@ static const struct mv88e6xxx_ops mv88e6161_ops = {
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
.stats_get_strings = mv88e6095_stats_get_strings,
.stats_get_stats = mv88e6095_stats_get_stats,
.stats_get_stat = mv88e6095_stats_get_stat,
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6097_watchdog_ops,
......@@ -4293,7 +4407,7 @@ static const struct mv88e6xxx_ops mv88e6165_ops = {
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
.stats_get_strings = mv88e6095_stats_get_strings,
.stats_get_stats = mv88e6095_stats_get_stats,
.stats_get_stat = mv88e6095_stats_get_stat,
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6097_watchdog_ops,
......@@ -4341,7 +4455,7 @@ static const struct mv88e6xxx_ops mv88e6171_ops = {
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
.stats_get_strings = mv88e6095_stats_get_strings,
.stats_get_stats = mv88e6095_stats_get_stats,
.stats_get_stat = mv88e6095_stats_get_stat,
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6097_watchdog_ops,
......@@ -4390,7 +4504,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = {
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
.stats_get_strings = mv88e6095_stats_get_strings,
.stats_get_stats = mv88e6095_stats_get_stats,
.stats_get_stat = mv88e6095_stats_get_stat,
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6097_watchdog_ops,
......@@ -4441,7 +4555,7 @@ static const struct mv88e6xxx_ops mv88e6175_ops = {
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
.stats_get_strings = mv88e6095_stats_get_strings,
.stats_get_stats = mv88e6095_stats_get_stats,
.stats_get_stat = mv88e6095_stats_get_stat,
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6097_watchdog_ops,
......@@ -4490,7 +4604,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = {
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
.stats_get_strings = mv88e6095_stats_get_strings,
.stats_get_stats = mv88e6095_stats_get_stats,
.stats_get_stat = mv88e6095_stats_get_stat,
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6097_watchdog_ops,
......@@ -4535,7 +4649,7 @@ static const struct mv88e6xxx_ops mv88e6185_ops = {
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
.stats_get_strings = mv88e6095_stats_get_strings,
.stats_get_stats = mv88e6095_stats_get_stats,
.stats_get_stat = mv88e6095_stats_get_stat,
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6097_watchdog_ops,
......@@ -4584,7 +4698,7 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
.stats_get_strings = mv88e6320_stats_get_strings,
.stats_get_stats = mv88e6390_stats_get_stats,
.stats_get_stat = mv88e6390_stats_get_stat,
.set_cpu_port = mv88e6390_g1_set_cpu_port,
.set_egress_port = mv88e6390_g1_set_egress_port,
.watchdog_ops = &mv88e6390_watchdog_ops,
......@@ -4642,7 +4756,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
.stats_get_strings = mv88e6320_stats_get_strings,
.stats_get_stats = mv88e6390_stats_get_stats,
.stats_get_stat = mv88e6390_stats_get_stat,
.set_cpu_port = mv88e6390_g1_set_cpu_port,
.set_egress_port = mv88e6390_g1_set_egress_port,
.watchdog_ops = &mv88e6390_watchdog_ops,
......@@ -4698,7 +4812,7 @@ static const struct mv88e6xxx_ops mv88e6191_ops = {
.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
.stats_get_strings = mv88e6320_stats_get_strings,
.stats_get_stats = mv88e6390_stats_get_stats,
.stats_get_stat = mv88e6390_stats_get_stat,
.set_cpu_port = mv88e6390_g1_set_cpu_port,
.set_egress_port = mv88e6390_g1_set_egress_port,
.watchdog_ops = &mv88e6390_watchdog_ops,
......@@ -4757,7 +4871,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
.stats_get_strings = mv88e6095_stats_get_strings,
.stats_get_stats = mv88e6095_stats_get_stats,
.stats_get_stat = mv88e6095_stats_get_stat,
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6097_watchdog_ops,
......@@ -4810,7 +4924,7 @@ static const struct mv88e6xxx_ops mv88e6250_ops = {
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6250_stats_get_sset_count,
.stats_get_strings = mv88e6250_stats_get_strings,
.stats_get_stats = mv88e6250_stats_get_stats,
.stats_get_stat = mv88e6250_stats_get_stat,
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6250_watchdog_ops,
......@@ -4857,7 +4971,7 @@ static const struct mv88e6xxx_ops mv88e6290_ops = {
.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
.stats_get_strings = mv88e6320_stats_get_strings,
.stats_get_stats = mv88e6390_stats_get_stats,
.stats_get_stat = mv88e6390_stats_get_stat,
.set_cpu_port = mv88e6390_g1_set_cpu_port,
.set_egress_port = mv88e6390_g1_set_egress_port,
.watchdog_ops = &mv88e6390_watchdog_ops,
......@@ -4916,7 +5030,7 @@ static const struct mv88e6xxx_ops mv88e6320_ops = {
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
.stats_get_strings = mv88e6320_stats_get_strings,
.stats_get_stats = mv88e6320_stats_get_stats,
.stats_get_stat = mv88e6320_stats_get_stat,
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6390_watchdog_ops,
......@@ -4963,7 +5077,7 @@ static const struct mv88e6xxx_ops mv88e6321_ops = {
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
.stats_get_strings = mv88e6320_stats_get_strings,
.stats_get_stats = mv88e6320_stats_get_stats,
.stats_get_stat = mv88e6320_stats_get_stat,
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6390_watchdog_ops,
......@@ -5012,7 +5126,7 @@ static const struct mv88e6xxx_ops mv88e6341_ops = {
.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
.stats_get_strings = mv88e6320_stats_get_strings,
.stats_get_stats = mv88e6390_stats_get_stats,
.stats_get_stat = mv88e6390_stats_get_stat,
.set_cpu_port = mv88e6390_g1_set_cpu_port,
.set_egress_port = mv88e6390_g1_set_egress_port,
.watchdog_ops = &mv88e6390_watchdog_ops,
......@@ -5070,7 +5184,7 @@ static const struct mv88e6xxx_ops mv88e6350_ops = {
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
.stats_get_strings = mv88e6095_stats_get_strings,
.stats_get_stats = mv88e6095_stats_get_stats,
.stats_get_stat = mv88e6095_stats_get_stat,
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6097_watchdog_ops,
......@@ -5116,7 +5230,7 @@ static const struct mv88e6xxx_ops mv88e6351_ops = {
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
.stats_get_strings = mv88e6095_stats_get_strings,
.stats_get_stats = mv88e6095_stats_get_stats,
.stats_get_stat = mv88e6095_stats_get_stat,
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6097_watchdog_ops,
......@@ -5167,7 +5281,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6095_stats_get_sset_count,
.stats_get_strings = mv88e6095_stats_get_strings,
.stats_get_stats = mv88e6095_stats_get_stats,
.stats_get_stat = mv88e6095_stats_get_stat,
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6097_watchdog_ops,
......@@ -5229,7 +5343,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
.stats_get_strings = mv88e6320_stats_get_strings,
.stats_get_stats = mv88e6390_stats_get_stats,
.stats_get_stat = mv88e6390_stats_get_stat,
.set_cpu_port = mv88e6390_g1_set_cpu_port,
.set_egress_port = mv88e6390_g1_set_egress_port,
.watchdog_ops = &mv88e6390_watchdog_ops,
......@@ -5291,7 +5405,7 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
.stats_get_strings = mv88e6320_stats_get_strings,
.stats_get_stats = mv88e6390_stats_get_stats,
.stats_get_stat = mv88e6390_stats_get_stat,
.set_cpu_port = mv88e6390_g1_set_cpu_port,
.set_egress_port = mv88e6390_g1_set_egress_port,
.watchdog_ops = &mv88e6390_watchdog_ops,
......@@ -5353,7 +5467,7 @@ static const struct mv88e6xxx_ops mv88e6393x_ops = {
.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6320_stats_get_sset_count,
.stats_get_strings = mv88e6320_stats_get_strings,
.stats_get_stats = mv88e6390_stats_get_stats,
.stats_get_stat = mv88e6390_stats_get_stat,
/* .set_cpu_port is missing because this family does not support a global
* CPU port, only per port CPU port which is set via
* .port_set_upstream_port method.
......@@ -6817,6 +6931,8 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
.phylink_mac_link_up = mv88e6xxx_mac_link_up,
.get_strings = mv88e6xxx_get_strings,
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
.get_eth_mac_stats = mv88e6xxx_get_eth_mac_stats,
.get_rmon_stats = mv88e6xxx_get_rmon_stats,
.get_sset_count = mv88e6xxx_get_sset_count,
.port_max_mtu = mv88e6xxx_get_max_mtu,
.port_change_mtu = mv88e6xxx_change_mtu,
......
......@@ -318,6 +318,17 @@ struct mv88e6xxx_mst {
struct mv88e6xxx_stu_entry stu;
};
#define STATS_TYPE_PORT BIT(0)
#define STATS_TYPE_BANK0 BIT(1)
#define STATS_TYPE_BANK1 BIT(2)
struct mv88e6xxx_hw_stat {
char string[ETH_GSTRING_LEN];
size_t size;
int reg;
int type;
};
struct mv88e6xxx_chip {
const struct mv88e6xxx_info *info;
......@@ -574,8 +585,9 @@ struct mv88e6xxx_ops {
/* Return the number of strings describing statistics */
int (*stats_get_sset_count)(struct mv88e6xxx_chip *chip);
int (*stats_get_strings)(struct mv88e6xxx_chip *chip, uint8_t *data);
int (*stats_get_stats)(struct mv88e6xxx_chip *chip, int port,
uint64_t *data);
size_t (*stats_get_stat)(struct mv88e6xxx_chip *chip, int port,
const struct mv88e6xxx_hw_stat *stat,
uint64_t *data);
int (*set_cpu_port)(struct mv88e6xxx_chip *chip, int port);
int (*set_egress_port)(struct mv88e6xxx_chip *chip,
enum mv88e6xxx_egress_direction direction,
......@@ -601,8 +613,8 @@ struct mv88e6xxx_ops {
int (*serdes_get_sset_count)(struct mv88e6xxx_chip *chip, int port);
int (*serdes_get_strings)(struct mv88e6xxx_chip *chip, int port,
uint8_t *data);
int (*serdes_get_stats)(struct mv88e6xxx_chip *chip, int port,
uint64_t *data);
size_t (*serdes_get_stats)(struct mv88e6xxx_chip *chip, int port,
uint64_t *data);
/* SERDES registers for ethtool */
int (*serdes_get_regs_len)(struct mv88e6xxx_chip *chip, int port);
......@@ -727,17 +739,6 @@ struct mv88e6xxx_pcs_ops {
};
#define STATS_TYPE_PORT BIT(0)
#define STATS_TYPE_BANK0 BIT(1)
#define STATS_TYPE_BANK1 BIT(2)
struct mv88e6xxx_hw_stat {
char string[ETH_GSTRING_LEN];
size_t size;
int reg;
int type;
};
static inline bool mv88e6xxx_has_stu(struct mv88e6xxx_chip *chip)
{
return chip->info->max_sid > 0 &&
......
......@@ -462,8 +462,7 @@ int mv88e6390_g1_rmu_disable(struct mv88e6xxx_chip *chip)
int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip)
{
return mv88e6xxx_g1_ctl2_mask(chip, MV88E6390_G1_CTL2_HIST_MODE_MASK,
MV88E6390_G1_CTL2_HIST_MODE_RX |
MV88E6390_G1_CTL2_HIST_MODE_TX);
MV88E6390_G1_CTL2_HIST_MODE_RX);
}
int mv88e6xxx_g1_set_device_number(struct mv88e6xxx_chip *chip, int index)
......@@ -491,7 +490,7 @@ int mv88e6095_g1_stats_set_histogram(struct mv88e6xxx_chip *chip)
if (err)
return err;
val |= MV88E6XXX_G1_STATS_OP_HIST_RX_TX;
val |= MV88E6XXX_G1_STATS_OP_HIST_RX;
err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP, val);
......@@ -506,7 +505,7 @@ int mv88e6xxx_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP,
MV88E6XXX_G1_STATS_OP_BUSY |
MV88E6XXX_G1_STATS_OP_CAPTURE_PORT |
MV88E6XXX_G1_STATS_OP_HIST_RX_TX | port);
MV88E6XXX_G1_STATS_OP_HIST_RX | port);
if (err)
return err;
......
......@@ -177,8 +177,8 @@ static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip *chip,
return val;
}
int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
uint64_t *data)
size_t mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
uint64_t *data)
{
struct mv88e6xxx_port *mv88e6xxx_port = &chip->ports[port];
struct mv88e6352_serdes_hw_stat *stat;
......@@ -187,7 +187,7 @@ int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
if (err <= 0)
return err;
return 0;
BUILD_BUG_ON(ARRAY_SIZE(mv88e6352_serdes_hw_stats) >
ARRAY_SIZE(mv88e6xxx_port->serdes_stats));
......@@ -429,8 +429,8 @@ static uint64_t mv88e6390_serdes_get_stat(struct mv88e6xxx_chip *chip, int lane,
return reg[0] | ((u64)reg[1] << 16) | ((u64)reg[2] << 32);
}
int mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
uint64_t *data)
size_t mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
uint64_t *data)
{
struct mv88e6390_serdes_hw_stat *stat;
int lane;
......
......@@ -127,13 +127,13 @@ unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip,
int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port);
int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
int port, uint8_t *data);
int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
uint64_t *data);
size_t mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
uint64_t *data);
int mv88e6390_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port);
int mv88e6390_serdes_get_strings(struct mv88e6xxx_chip *chip,
int port, uint8_t *data);
int mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
uint64_t *data);
size_t mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
uint64_t *data);
int mv88e6352_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port);
void mv88e6352_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p);
......
......@@ -17,6 +17,7 @@ TEST_PROGS = bridge_fdb_learning_limit.sh \
dual_vxlan_bridge.sh \
ethtool_extended_state.sh \
ethtool_mm.sh \
ethtool_rmon.sh \
ethtool.sh \
gre_custom_multipath_hash.sh \
gre_inner_v4_multipath.sh \
......
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
ALL_TESTS="
rmon_rx_histogram
rmon_tx_histogram
"
NUM_NETIFS=2
source lib.sh
ETH_FCS_LEN=4
ETH_HLEN=$((6+6+2))
declare -A netif_mtu
ensure_mtu()
{
local iface=$1; shift
local len=$1; shift
local current=$(ip -j link show dev $iface | jq -r '.[0].mtu')
local required=$((len - ETH_HLEN - ETH_FCS_LEN))
if [ $current -lt $required ]; then
ip link set dev $iface mtu $required || return 1
fi
}
bucket_test()
{
local iface=$1; shift
local neigh=$1; shift
local set=$1; shift
local bucket=$1; shift
local len=$1; shift
local num_rx=10000
local num_tx=20000
local expected=
local before=
local after=
local delta=
# Mausezahn does not include FCS bytes in its length - but the
# histogram counters do
len=$((len - ETH_FCS_LEN))
before=$(ethtool --json -S $iface --groups rmon | \
jq -r ".[0].rmon[\"${set}-pktsNtoM\"][$bucket].val")
# Send 10k one way and 20k in the other, to detect counters
# mapped to the wrong direction
$MZ $neigh -q -c $num_rx -p $len -a own -b bcast -d 10us
$MZ $iface -q -c $num_tx -p $len -a own -b bcast -d 10us
after=$(ethtool --json -S $iface --groups rmon | \
jq -r ".[0].rmon[\"${set}-pktsNtoM\"][$bucket].val")
delta=$((after - before))
expected=$([ $set = rx ] && echo $num_rx || echo $num_tx)
# Allow some extra tolerance for other packets sent by the stack
[ $delta -ge $expected ] && [ $delta -le $((expected + 100)) ]
}
rmon_histogram()
{
local iface=$1; shift
local neigh=$1; shift
local set=$1; shift
local nbuckets=0
local step=
RET=0
while read -r -a bucket; do
step="$set-pkts${bucket[0]}to${bucket[1]} on $iface"
for if in $iface $neigh; do
if ! ensure_mtu $if ${bucket[0]}; then
log_test_skip "$if does not support the required MTU for $step"
return
fi
done
if ! bucket_test $iface $neigh $set $nbuckets ${bucket[0]}; then
check_err 1 "$step failed"
return 1
fi
log_test "$step"
nbuckets=$((nbuckets + 1))
done < <(ethtool --json -S $iface --groups rmon | \
jq -r ".[0].rmon[\"${set}-pktsNtoM\"][]|[.low, .high]|@tsv" 2>/dev/null)
if [ $nbuckets -eq 0 ]; then
log_test_skip "$iface does not support $set histogram counters"
return
fi
}
rmon_rx_histogram()
{
rmon_histogram $h1 $h2 rx
rmon_histogram $h2 $h1 rx
}
rmon_tx_histogram()
{
rmon_histogram $h1 $h2 tx
rmon_histogram $h2 $h1 tx
}
setup_prepare()
{
h1=${NETIFS[p1]}
h2=${NETIFS[p2]}
for iface in $h1 $h2; do
netif_mtu[$iface]=$(ip -j link show dev $iface | jq -r '.[0].mtu')
ip link set dev $iface up
done
}
cleanup()
{
pre_cleanup
for iface in $h2 $h1; do
ip link set dev $iface \
mtu ${netif_mtu[$iface]} \
down
done
}
check_ethtool_counter_group_support
trap cleanup EXIT
setup_prepare
setup_wait
tests_run
exit $EXIT_STATUS
......@@ -146,6 +146,15 @@ check_ethtool_mm_support()
fi
}
check_ethtool_counter_group_support()
{
ethtool --help 2>&1| grep -- '--all-groups' &> /dev/null
if [[ $? -ne 0 ]]; then
echo "SKIP: ethtool too old; it is missing standard counter group support"
exit $ksft_skip
fi
}
check_locked_port_support()
{
if ! bridge -d link show | grep -q " locked"; then
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment