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

Merge branch 'dsa-Add-ATU-VTU-statistics'

Andrew Lunn says:

====================
Add ATU/VTU statistics

Previous patches have added basic support for Address Translation Unit
and VLAN translation Unit violation interrupts. Add statistics
counters for when these occur, which can be accessed using
ethtool. Downgrade one of the particularly spammy warnings from VTU
violations to debug only, now that we have a counter for it.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 7ae665f1 7f20d834
...@@ -723,6 +723,24 @@ static int mv88e6320_stats_get_strings(struct mv88e6xxx_chip *chip, ...@@ -723,6 +723,24 @@ static int mv88e6320_stats_get_strings(struct mv88e6xxx_chip *chip,
STATS_TYPE_BANK0 | STATS_TYPE_BANK1); STATS_TYPE_BANK0 | STATS_TYPE_BANK1);
} }
static const uint8_t *mv88e6xxx_atu_vtu_stats_strings[] = {
"atu_member_violation",
"atu_miss_violation",
"atu_full_violation",
"vtu_member_violation",
"vtu_miss_violation",
};
static void mv88e6xxx_atu_vtu_get_strings(uint8_t *data)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(mv88e6xxx_atu_vtu_stats_strings); i++)
strlcpy(data + i * ETH_GSTRING_LEN,
mv88e6xxx_atu_vtu_stats_strings[i],
ETH_GSTRING_LEN);
}
static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port, static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port,
uint8_t *data) uint8_t *data)
{ {
...@@ -736,9 +754,12 @@ static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port, ...@@ -736,9 +754,12 @@ static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port,
if (chip->info->ops->serdes_get_strings) { if (chip->info->ops->serdes_get_strings) {
data += count * ETH_GSTRING_LEN; data += count * ETH_GSTRING_LEN;
chip->info->ops->serdes_get_strings(chip, port, data); count = chip->info->ops->serdes_get_strings(chip, port, data);
} }
data += count * ETH_GSTRING_LEN;
mv88e6xxx_atu_vtu_get_strings(data);
mutex_unlock(&chip->reg_lock); mutex_unlock(&chip->reg_lock);
} }
...@@ -783,10 +804,13 @@ static int mv88e6xxx_get_sset_count(struct dsa_switch *ds, int port) ...@@ -783,10 +804,13 @@ static int mv88e6xxx_get_sset_count(struct dsa_switch *ds, int port)
if (chip->info->ops->serdes_get_sset_count) if (chip->info->ops->serdes_get_sset_count)
serdes_count = chip->info->ops->serdes_get_sset_count(chip, serdes_count = chip->info->ops->serdes_get_sset_count(chip,
port); port);
if (serdes_count < 0) if (serdes_count < 0) {
count = serdes_count; count = serdes_count;
else goto out;
}
count += serdes_count; count += serdes_count;
count += ARRAY_SIZE(mv88e6xxx_atu_vtu_stats_strings);
out: out:
mutex_unlock(&chip->reg_lock); mutex_unlock(&chip->reg_lock);
...@@ -841,6 +865,16 @@ static int mv88e6390_stats_get_stats(struct mv88e6xxx_chip *chip, int port, ...@@ -841,6 +865,16 @@ static int mv88e6390_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
0); 0);
} }
static void mv88e6xxx_atu_vtu_get_stats(struct mv88e6xxx_chip *chip, int port,
uint64_t *data)
{
*data++ = chip->ports[port].atu_member_violation;
*data++ = chip->ports[port].atu_miss_violation;
*data++ = chip->ports[port].atu_full_violation;
*data++ = chip->ports[port].vtu_member_violation;
*data++ = chip->ports[port].vtu_miss_violation;
}
static void mv88e6xxx_get_stats(struct mv88e6xxx_chip *chip, int port, static void mv88e6xxx_get_stats(struct mv88e6xxx_chip *chip, int port,
uint64_t *data) uint64_t *data)
{ {
...@@ -849,12 +883,14 @@ static void mv88e6xxx_get_stats(struct mv88e6xxx_chip *chip, int port, ...@@ -849,12 +883,14 @@ static void mv88e6xxx_get_stats(struct mv88e6xxx_chip *chip, int port,
if (chip->info->ops->stats_get_stats) if (chip->info->ops->stats_get_stats)
count = chip->info->ops->stats_get_stats(chip, port, data); count = chip->info->ops->stats_get_stats(chip, port, data);
mutex_lock(&chip->reg_lock);
if (chip->info->ops->serdes_get_stats) { if (chip->info->ops->serdes_get_stats) {
data += count; data += count;
mutex_lock(&chip->reg_lock); count = chip->info->ops->serdes_get_stats(chip, port, data);
chip->info->ops->serdes_get_stats(chip, port, data);
mutex_unlock(&chip->reg_lock);
} }
data += count;
mv88e6xxx_atu_vtu_get_stats(chip, port, data);
mutex_unlock(&chip->reg_lock);
} }
static void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port, static void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
......
...@@ -194,6 +194,11 @@ struct mv88e6xxx_port_hwtstamp { ...@@ -194,6 +194,11 @@ struct mv88e6xxx_port_hwtstamp {
struct mv88e6xxx_port { struct mv88e6xxx_port {
u64 serdes_stats[2]; u64 serdes_stats[2];
u64 atu_member_violation;
u64 atu_miss_violation;
u64 atu_full_violation;
u64 vtu_member_violation;
u64 vtu_miss_violation;
}; };
struct mv88e6xxx_chip { struct mv88e6xxx_chip {
...@@ -409,9 +414,9 @@ struct mv88e6xxx_ops { ...@@ -409,9 +414,9 @@ struct mv88e6xxx_ops {
/* Statistics from the SERDES interface */ /* Statistics from the SERDES interface */
int (*serdes_get_sset_count)(struct mv88e6xxx_chip *chip, int port); int (*serdes_get_sset_count)(struct mv88e6xxx_chip *chip, int port);
void (*serdes_get_strings)(struct mv88e6xxx_chip *chip, int port, int (*serdes_get_strings)(struct mv88e6xxx_chip *chip, int port,
uint8_t *data); uint8_t *data);
void (*serdes_get_stats)(struct mv88e6xxx_chip *chip, int port, int (*serdes_get_stats)(struct mv88e6xxx_chip *chip, int port,
uint64_t *data); uint64_t *data);
/* VLAN Translation Unit operations */ /* VLAN Translation Unit operations */
......
...@@ -336,8 +336,6 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id) ...@@ -336,8 +336,6 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id)
if (err) if (err)
goto out; goto out;
mutex_unlock(&chip->reg_lock);
if (val & MV88E6XXX_G1_ATU_OP_AGE_OUT_VIOLATION) { if (val & MV88E6XXX_G1_ATU_OP_AGE_OUT_VIOLATION) {
dev_err_ratelimited(chip->dev, dev_err_ratelimited(chip->dev,
"ATU age out violation for %pM\n", "ATU age out violation for %pM\n",
...@@ -348,17 +346,23 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id) ...@@ -348,17 +346,23 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id)
dev_err_ratelimited(chip->dev, dev_err_ratelimited(chip->dev,
"ATU member violation for %pM portvec %x\n", "ATU member violation for %pM portvec %x\n",
entry.mac, entry.portvec); entry.mac, entry.portvec);
chip->ports[entry.portvec].atu_member_violation++;
} }
if (val & MV88E6XXX_G1_ATU_OP_MEMBER_VIOLATION) if (val & MV88E6XXX_G1_ATU_OP_MEMBER_VIOLATION) {
dev_err_ratelimited(chip->dev, dev_err_ratelimited(chip->dev,
"ATU miss violation for %pM portvec %x\n", "ATU miss violation for %pM portvec %x\n",
entry.mac, entry.portvec); entry.mac, entry.portvec);
chip->ports[entry.portvec].atu_miss_violation++;
}
if (val & MV88E6XXX_G1_ATU_OP_FULL_VIOLATION) if (val & MV88E6XXX_G1_ATU_OP_FULL_VIOLATION) {
dev_err_ratelimited(chip->dev, dev_err_ratelimited(chip->dev,
"ATU full violation for %pM portvec %x\n", "ATU full violation for %pM portvec %x\n",
entry.mac, entry.portvec); entry.mac, entry.portvec);
chip->ports[entry.portvec].atu_full_violation++;
}
mutex_unlock(&chip->reg_lock);
return IRQ_HANDLED; return IRQ_HANDLED;
......
...@@ -539,18 +539,21 @@ static irqreturn_t mv88e6xxx_g1_vtu_prob_irq_thread_fn(int irq, void *dev_id) ...@@ -539,18 +539,21 @@ static irqreturn_t mv88e6xxx_g1_vtu_prob_irq_thread_fn(int irq, void *dev_id)
if (err) if (err)
goto out; goto out;
mutex_unlock(&chip->reg_lock);
spid = val & MV88E6XXX_G1_VTU_OP_SPID_MASK; spid = val & MV88E6XXX_G1_VTU_OP_SPID_MASK;
if (val & MV88E6XXX_G1_VTU_OP_MEMBER_VIOLATION) { if (val & MV88E6XXX_G1_VTU_OP_MEMBER_VIOLATION) {
dev_err_ratelimited(chip->dev, "VTU member violation for vid %d, source port %d\n", dev_err_ratelimited(chip->dev, "VTU member violation for vid %d, source port %d\n",
entry.vid, spid); entry.vid, spid);
chip->ports[spid].vtu_member_violation++;
} }
if (val & MV88E6XXX_G1_VTU_OP_MISS_VIOLATION) if (val & MV88E6XXX_G1_VTU_OP_MISS_VIOLATION) {
dev_err_ratelimited(chip->dev, "VTU miss violation for vid %d, source port %d\n", dev_dbg_ratelimited(chip->dev, "VTU miss violation for vid %d, source port %d\n",
entry.vid, spid); entry.vid, spid);
chip->ports[spid].vtu_miss_violation++;
}
mutex_unlock(&chip->reg_lock);
return IRQ_HANDLED; return IRQ_HANDLED;
......
...@@ -106,20 +106,21 @@ int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port) ...@@ -106,20 +106,21 @@ int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
return 0; return 0;
} }
void mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip, int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
int port, uint8_t *data) int port, uint8_t *data)
{ {
struct mv88e6352_serdes_hw_stat *stat; struct mv88e6352_serdes_hw_stat *stat;
int i; int i;
if (!mv88e6352_port_has_serdes(chip, port)) if (!mv88e6352_port_has_serdes(chip, port))
return; return 0;
for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) { for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) {
stat = &mv88e6352_serdes_hw_stats[i]; stat = &mv88e6352_serdes_hw_stats[i];
memcpy(data + i * ETH_GSTRING_LEN, stat->string, memcpy(data + i * ETH_GSTRING_LEN, stat->string,
ETH_GSTRING_LEN); ETH_GSTRING_LEN);
} }
return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
} }
static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip *chip, static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip *chip,
...@@ -149,7 +150,7 @@ static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip *chip, ...@@ -149,7 +150,7 @@ static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip *chip,
return val; return val;
} }
void mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
uint64_t *data) uint64_t *data)
{ {
struct mv88e6xxx_port *mv88e6xxx_port = &chip->ports[port]; struct mv88e6xxx_port *mv88e6xxx_port = &chip->ports[port];
...@@ -158,7 +159,7 @@ void mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, ...@@ -158,7 +159,7 @@ void mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
int i; int i;
if (!mv88e6352_port_has_serdes(chip, port)) if (!mv88e6352_port_has_serdes(chip, port))
return; return 0;
BUILD_BUG_ON(ARRAY_SIZE(mv88e6352_serdes_hw_stats) > BUILD_BUG_ON(ARRAY_SIZE(mv88e6352_serdes_hw_stats) >
ARRAY_SIZE(mv88e6xxx_port->serdes_stats)); ARRAY_SIZE(mv88e6xxx_port->serdes_stats));
...@@ -169,6 +170,8 @@ void mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, ...@@ -169,6 +170,8 @@ void mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
mv88e6xxx_port->serdes_stats[i] += value; mv88e6xxx_port->serdes_stats[i] += value;
data[i] = mv88e6xxx_port->serdes_stats[i]; data[i] = mv88e6xxx_port->serdes_stats[i];
} }
return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
} }
/* Set the power on/off for 10GBASE-R and 10GBASE-X4/X2 */ /* Set the power on/off for 10GBASE-R and 10GBASE-X4/X2 */
......
...@@ -45,8 +45,8 @@ ...@@ -45,8 +45,8 @@
int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on); int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on);
int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on); int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on);
int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port); int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port);
void mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip, int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
int port, uint8_t *data); int port, uint8_t *data);
void mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
uint64_t *data); uint64_t *data);
#endif #endif
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