summaryrefslogtreecommitdiffstats
path: root/drivers/net/dsa/mv88e6xxx/chip.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/dsa/mv88e6xxx/chip.c')
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.c454
1 files changed, 311 insertions, 143 deletions
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index dd2cbffcfe..32416d8802 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -566,13 +566,61 @@ static void mv88e6xxx_translate_cmode(u8 cmode, unsigned long *supported)
phy_interface_set_rgmii(supported);
}
-static void mv88e6250_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
- struct phylink_config *config)
+static void
+mv88e6250_setup_supported_interfaces(struct mv88e6xxx_chip *chip, int port,
+ struct phylink_config *config)
{
unsigned long *supported = config->supported_interfaces;
+ int err;
+ u16 reg;
- /* Translate the default cmode */
- mv88e6xxx_translate_cmode(chip->ports[port].cmode, supported);
+ err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
+ if (err) {
+ dev_err(chip->dev, "p%d: failed to read port status\n", port);
+ return;
+ }
+
+ switch (reg & MV88E6250_PORT_STS_PORTMODE_MASK) {
+ case MV88E6250_PORT_STS_PORTMODE_MII_10_HALF_PHY:
+ case MV88E6250_PORT_STS_PORTMODE_MII_100_HALF_PHY:
+ case MV88E6250_PORT_STS_PORTMODE_MII_10_FULL_PHY:
+ case MV88E6250_PORT_STS_PORTMODE_MII_100_FULL_PHY:
+ __set_bit(PHY_INTERFACE_MODE_REVMII, supported);
+ break;
+
+ case MV88E6250_PORT_STS_PORTMODE_MII_HALF:
+ case MV88E6250_PORT_STS_PORTMODE_MII_FULL:
+ __set_bit(PHY_INTERFACE_MODE_MII, supported);
+ break;
+
+ case MV88E6250_PORT_STS_PORTMODE_MII_DUAL_100_RMII_FULL_PHY:
+ case MV88E6250_PORT_STS_PORTMODE_MII_200_RMII_FULL_PHY:
+ case MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_HALF_PHY:
+ case MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_FULL_PHY:
+ __set_bit(PHY_INTERFACE_MODE_REVRMII, supported);
+ break;
+
+ case MV88E6250_PORT_STS_PORTMODE_MII_DUAL_100_RMII_FULL:
+ case MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_FULL:
+ __set_bit(PHY_INTERFACE_MODE_RMII, supported);
+ break;
+
+ case MV88E6250_PORT_STS_PORTMODE_MII_100_RGMII:
+ __set_bit(PHY_INTERFACE_MODE_RGMII, supported);
+ break;
+
+ default:
+ dev_err(chip->dev,
+ "p%d: invalid port mode in status register: %04x\n",
+ port, reg);
+ }
+}
+
+static void mv88e6250_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
+ struct phylink_config *config)
+{
+ if (!mv88e6xxx_phy_is_internal(chip, port))
+ mv88e6250_setup_supported_interfaces(chip, port, config);
config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100;
}
@@ -943,76 +991,94 @@ error:
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 +1121,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 +1202,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 +1261,82 @@ out:
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 +1352,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 +1372,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 +4149,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 +4187,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 +4228,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 +4270,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 +4313,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 +4362,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 +4417,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 +4455,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 +4503,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 +4552,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 +4603,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 +4652,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 +4697,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 +4746,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 +4804,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 +4860,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 +4919,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 +4972,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 +5019,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 +5078,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 +5125,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 +5174,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 +5232,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 +5278,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 +5329,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 +5391,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 +5453,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 +5515,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.
@@ -5386,8 +5548,12 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.family = MV88E6XXX_FAMILY_6250,
.name = "Marvell 88E6020",
.num_databases = 64,
- .num_ports = 4,
+ /* Ports 2-4 are not routed to pins
+ * => usable ports 0, 1, 5, 6
+ */
+ .num_ports = 7,
.num_internal_phys = 2,
+ .invalid_port_mask = BIT(2) | BIT(3) | BIT(4),
.max_vid = 4095,
.port_base_addr = 0x8,
.phy_base_addr = 0x0,
@@ -6817,6 +6983,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,