diff options
author | Andrew Lunn <andrew@lunn.ch> | 2018-03-28 17:50:28 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-03-29 15:04:22 -0400 |
commit | 65f60e4582bd321f4df1433a22f717f18e60f721 (patch) | |
tree | 9f2577306ba82031773faea60ffc8381c1ebc47a | |
parent | 7ae665f132a62e67ccef1ef0994acba51abc2400 (diff) |
net: dsa: mv88e6xxx: Keep ATU/VTU violation statistics
Count the numbers of various ATU and VTU violation statistics and
return them as part of the ethtool -S statistics.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/chip.c | 50 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/chip.h | 13 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/global1_atu.c | 12 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/global1_vtu.c | 8 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/serdes.c | 15 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/serdes.h | 8 |
6 files changed, 78 insertions, 28 deletions
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 9a5d786b4885..3d2091099f7f 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c | |||
@@ -723,6 +723,24 @@ static int mv88e6320_stats_get_strings(struct mv88e6xxx_chip *chip, | |||
723 | STATS_TYPE_BANK0 | STATS_TYPE_BANK1); | 723 | STATS_TYPE_BANK0 | STATS_TYPE_BANK1); |
724 | } | 724 | } |
725 | 725 | ||
726 | static const uint8_t *mv88e6xxx_atu_vtu_stats_strings[] = { | ||
727 | "atu_member_violation", | ||
728 | "atu_miss_violation", | ||
729 | "atu_full_violation", | ||
730 | "vtu_member_violation", | ||
731 | "vtu_miss_violation", | ||
732 | }; | ||
733 | |||
734 | static void mv88e6xxx_atu_vtu_get_strings(uint8_t *data) | ||
735 | { | ||
736 | unsigned int i; | ||
737 | |||
738 | for (i = 0; i < ARRAY_SIZE(mv88e6xxx_atu_vtu_stats_strings); i++) | ||
739 | strlcpy(data + i * ETH_GSTRING_LEN, | ||
740 | mv88e6xxx_atu_vtu_stats_strings[i], | ||
741 | ETH_GSTRING_LEN); | ||
742 | } | ||
743 | |||
726 | static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port, | 744 | static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port, |
727 | uint8_t *data) | 745 | uint8_t *data) |
728 | { | 746 | { |
@@ -736,9 +754,12 @@ static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port, | |||
736 | 754 | ||
737 | if (chip->info->ops->serdes_get_strings) { | 755 | if (chip->info->ops->serdes_get_strings) { |
738 | data += count * ETH_GSTRING_LEN; | 756 | data += count * ETH_GSTRING_LEN; |
739 | chip->info->ops->serdes_get_strings(chip, port, data); | 757 | count = chip->info->ops->serdes_get_strings(chip, port, data); |
740 | } | 758 | } |
741 | 759 | ||
760 | data += count * ETH_GSTRING_LEN; | ||
761 | mv88e6xxx_atu_vtu_get_strings(data); | ||
762 | |||
742 | mutex_unlock(&chip->reg_lock); | 763 | mutex_unlock(&chip->reg_lock); |
743 | } | 764 | } |
744 | 765 | ||
@@ -783,10 +804,13 @@ static int mv88e6xxx_get_sset_count(struct dsa_switch *ds, int port) | |||
783 | if (chip->info->ops->serdes_get_sset_count) | 804 | if (chip->info->ops->serdes_get_sset_count) |
784 | serdes_count = chip->info->ops->serdes_get_sset_count(chip, | 805 | serdes_count = chip->info->ops->serdes_get_sset_count(chip, |
785 | port); | 806 | port); |
786 | if (serdes_count < 0) | 807 | if (serdes_count < 0) { |
787 | count = serdes_count; | 808 | count = serdes_count; |
788 | else | 809 | goto out; |
789 | count += serdes_count; | 810 | } |
811 | count += serdes_count; | ||
812 | count += ARRAY_SIZE(mv88e6xxx_atu_vtu_stats_strings); | ||
813 | |||
790 | out: | 814 | out: |
791 | mutex_unlock(&chip->reg_lock); | 815 | mutex_unlock(&chip->reg_lock); |
792 | 816 | ||
@@ -841,6 +865,16 @@ static int mv88e6390_stats_get_stats(struct mv88e6xxx_chip *chip, int port, | |||
841 | 0); | 865 | 0); |
842 | } | 866 | } |
843 | 867 | ||
868 | static void mv88e6xxx_atu_vtu_get_stats(struct mv88e6xxx_chip *chip, int port, | ||
869 | uint64_t *data) | ||
870 | { | ||
871 | *data++ = chip->ports[port].atu_member_violation; | ||
872 | *data++ = chip->ports[port].atu_miss_violation; | ||
873 | *data++ = chip->ports[port].atu_full_violation; | ||
874 | *data++ = chip->ports[port].vtu_member_violation; | ||
875 | *data++ = chip->ports[port].vtu_miss_violation; | ||
876 | } | ||
877 | |||
844 | static void mv88e6xxx_get_stats(struct mv88e6xxx_chip *chip, int port, | 878 | static void mv88e6xxx_get_stats(struct mv88e6xxx_chip *chip, int port, |
845 | uint64_t *data) | 879 | uint64_t *data) |
846 | { | 880 | { |
@@ -849,12 +883,14 @@ static void mv88e6xxx_get_stats(struct mv88e6xxx_chip *chip, int port, | |||
849 | if (chip->info->ops->stats_get_stats) | 883 | if (chip->info->ops->stats_get_stats) |
850 | count = chip->info->ops->stats_get_stats(chip, port, data); | 884 | count = chip->info->ops->stats_get_stats(chip, port, data); |
851 | 885 | ||
886 | mutex_lock(&chip->reg_lock); | ||
852 | if (chip->info->ops->serdes_get_stats) { | 887 | if (chip->info->ops->serdes_get_stats) { |
853 | data += count; | 888 | data += count; |
854 | mutex_lock(&chip->reg_lock); | 889 | count = chip->info->ops->serdes_get_stats(chip, port, data); |
855 | chip->info->ops->serdes_get_stats(chip, port, data); | ||
856 | mutex_unlock(&chip->reg_lock); | ||
857 | } | 890 | } |
891 | data += count; | ||
892 | mv88e6xxx_atu_vtu_get_stats(chip, port, data); | ||
893 | mutex_unlock(&chip->reg_lock); | ||
858 | } | 894 | } |
859 | 895 | ||
860 | static void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port, | 896 | static void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port, |
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index bad211014e91..80490f66bc06 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h | |||
@@ -194,6 +194,11 @@ struct mv88e6xxx_port_hwtstamp { | |||
194 | 194 | ||
195 | struct mv88e6xxx_port { | 195 | struct mv88e6xxx_port { |
196 | u64 serdes_stats[2]; | 196 | u64 serdes_stats[2]; |
197 | u64 atu_member_violation; | ||
198 | u64 atu_miss_violation; | ||
199 | u64 atu_full_violation; | ||
200 | u64 vtu_member_violation; | ||
201 | u64 vtu_miss_violation; | ||
197 | }; | 202 | }; |
198 | 203 | ||
199 | struct mv88e6xxx_chip { | 204 | struct mv88e6xxx_chip { |
@@ -409,10 +414,10 @@ struct mv88e6xxx_ops { | |||
409 | 414 | ||
410 | /* Statistics from the SERDES interface */ | 415 | /* Statistics from the SERDES interface */ |
411 | int (*serdes_get_sset_count)(struct mv88e6xxx_chip *chip, int port); | 416 | int (*serdes_get_sset_count)(struct mv88e6xxx_chip *chip, int port); |
412 | void (*serdes_get_strings)(struct mv88e6xxx_chip *chip, int port, | 417 | int (*serdes_get_strings)(struct mv88e6xxx_chip *chip, int port, |
413 | uint8_t *data); | 418 | uint8_t *data); |
414 | void (*serdes_get_stats)(struct mv88e6xxx_chip *chip, int port, | 419 | int (*serdes_get_stats)(struct mv88e6xxx_chip *chip, int port, |
415 | uint64_t *data); | 420 | uint64_t *data); |
416 | 421 | ||
417 | /* VLAN Translation Unit operations */ | 422 | /* VLAN Translation Unit operations */ |
418 | int (*vtu_getnext)(struct mv88e6xxx_chip *chip, | 423 | int (*vtu_getnext)(struct mv88e6xxx_chip *chip, |
diff --git a/drivers/net/dsa/mv88e6xxx/global1_atu.c b/drivers/net/dsa/mv88e6xxx/global1_atu.c index 20d941f4273b..307410898fc9 100644 --- a/drivers/net/dsa/mv88e6xxx/global1_atu.c +++ b/drivers/net/dsa/mv88e6xxx/global1_atu.c | |||
@@ -336,8 +336,6 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id) | |||
336 | if (err) | 336 | if (err) |
337 | goto out; | 337 | goto out; |
338 | 338 | ||
339 | mutex_unlock(&chip->reg_lock); | ||
340 | |||
341 | if (val & MV88E6XXX_G1_ATU_OP_AGE_OUT_VIOLATION) { | 339 | if (val & MV88E6XXX_G1_ATU_OP_AGE_OUT_VIOLATION) { |
342 | dev_err_ratelimited(chip->dev, | 340 | dev_err_ratelimited(chip->dev, |
343 | "ATU age out violation for %pM\n", | 341 | "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 | dev_err_ratelimited(chip->dev, | 346 | dev_err_ratelimited(chip->dev, |
349 | "ATU member violation for %pM portvec %x\n", | 347 | "ATU member violation for %pM portvec %x\n", |
350 | entry.mac, entry.portvec); | 348 | entry.mac, entry.portvec); |
349 | chip->ports[entry.portvec].atu_member_violation++; | ||
351 | } | 350 | } |
352 | 351 | ||
353 | if (val & MV88E6XXX_G1_ATU_OP_MEMBER_VIOLATION) | 352 | if (val & MV88E6XXX_G1_ATU_OP_MEMBER_VIOLATION) { |
354 | dev_err_ratelimited(chip->dev, | 353 | dev_err_ratelimited(chip->dev, |
355 | "ATU miss violation for %pM portvec %x\n", | 354 | "ATU miss violation for %pM portvec %x\n", |
356 | entry.mac, entry.portvec); | 355 | entry.mac, entry.portvec); |
356 | chip->ports[entry.portvec].atu_miss_violation++; | ||
357 | } | ||
357 | 358 | ||
358 | if (val & MV88E6XXX_G1_ATU_OP_FULL_VIOLATION) | 359 | if (val & MV88E6XXX_G1_ATU_OP_FULL_VIOLATION) { |
359 | dev_err_ratelimited(chip->dev, | 360 | dev_err_ratelimited(chip->dev, |
360 | "ATU full violation for %pM portvec %x\n", | 361 | "ATU full violation for %pM portvec %x\n", |
361 | entry.mac, entry.portvec); | 362 | entry.mac, entry.portvec); |
363 | chip->ports[entry.portvec].atu_full_violation++; | ||
364 | } | ||
365 | mutex_unlock(&chip->reg_lock); | ||
362 | 366 | ||
363 | return IRQ_HANDLED; | 367 | return IRQ_HANDLED; |
364 | 368 | ||
diff --git a/drivers/net/dsa/mv88e6xxx/global1_vtu.c b/drivers/net/dsa/mv88e6xxx/global1_vtu.c index 7997961647de..2cbaf946e7ed 100644 --- a/drivers/net/dsa/mv88e6xxx/global1_vtu.c +++ b/drivers/net/dsa/mv88e6xxx/global1_vtu.c | |||
@@ -539,18 +539,20 @@ static irqreturn_t mv88e6xxx_g1_vtu_prob_irq_thread_fn(int irq, void *dev_id) | |||
539 | if (err) | 539 | if (err) |
540 | goto out; | 540 | goto out; |
541 | 541 | ||
542 | mutex_unlock(&chip->reg_lock); | ||
543 | |||
544 | spid = val & MV88E6XXX_G1_VTU_OP_SPID_MASK; | 542 | spid = val & MV88E6XXX_G1_VTU_OP_SPID_MASK; |
545 | 543 | ||
546 | if (val & MV88E6XXX_G1_VTU_OP_MEMBER_VIOLATION) { | 544 | if (val & MV88E6XXX_G1_VTU_OP_MEMBER_VIOLATION) { |
547 | dev_err_ratelimited(chip->dev, "VTU member violation for vid %d, source port %d\n", | 545 | dev_err_ratelimited(chip->dev, "VTU member violation for vid %d, source port %d\n", |
548 | entry.vid, spid); | 546 | entry.vid, spid); |
547 | chip->ports[spid].vtu_member_violation++; | ||
549 | } | 548 | } |
550 | 549 | ||
551 | if (val & MV88E6XXX_G1_VTU_OP_MISS_VIOLATION) | 550 | if (val & MV88E6XXX_G1_VTU_OP_MISS_VIOLATION) { |
552 | dev_err_ratelimited(chip->dev, "VTU miss violation for vid %d, source port %d\n", | 551 | dev_err_ratelimited(chip->dev, "VTU miss violation for vid %d, source port %d\n", |
553 | entry.vid, spid); | 552 | entry.vid, spid); |
553 | chip->ports[spid].vtu_miss_violation++; | ||
554 | } | ||
555 | mutex_unlock(&chip->reg_lock); | ||
554 | 556 | ||
555 | return IRQ_HANDLED; | 557 | return IRQ_HANDLED; |
556 | 558 | ||
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c index b6166424216a..fb058fd35c0d 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.c +++ b/drivers/net/dsa/mv88e6xxx/serdes.c | |||
@@ -106,20 +106,21 @@ int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port) | |||
106 | return 0; | 106 | return 0; |
107 | } | 107 | } |
108 | 108 | ||
109 | void mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip, | 109 | int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip, |
110 | int port, uint8_t *data) | 110 | int port, uint8_t *data) |
111 | { | 111 | { |
112 | struct mv88e6352_serdes_hw_stat *stat; | 112 | struct mv88e6352_serdes_hw_stat *stat; |
113 | int i; | 113 | int i; |
114 | 114 | ||
115 | if (!mv88e6352_port_has_serdes(chip, port)) | 115 | if (!mv88e6352_port_has_serdes(chip, port)) |
116 | return; | 116 | return 0; |
117 | 117 | ||
118 | for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) { | 118 | for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) { |
119 | stat = &mv88e6352_serdes_hw_stats[i]; | 119 | stat = &mv88e6352_serdes_hw_stats[i]; |
120 | memcpy(data + i * ETH_GSTRING_LEN, stat->string, | 120 | memcpy(data + i * ETH_GSTRING_LEN, stat->string, |
121 | ETH_GSTRING_LEN); | 121 | ETH_GSTRING_LEN); |
122 | } | 122 | } |
123 | return ARRAY_SIZE(mv88e6352_serdes_hw_stats); | ||
123 | } | 124 | } |
124 | 125 | ||
125 | static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip *chip, | 126 | static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip *chip, |
@@ -149,8 +150,8 @@ static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip *chip, | |||
149 | return val; | 150 | return val; |
150 | } | 151 | } |
151 | 152 | ||
152 | void mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, | 153 | int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, |
153 | uint64_t *data) | 154 | uint64_t *data) |
154 | { | 155 | { |
155 | struct mv88e6xxx_port *mv88e6xxx_port = &chip->ports[port]; | 156 | struct mv88e6xxx_port *mv88e6xxx_port = &chip->ports[port]; |
156 | struct mv88e6352_serdes_hw_stat *stat; | 157 | struct mv88e6352_serdes_hw_stat *stat; |
@@ -158,7 +159,7 @@ void mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, | |||
158 | int i; | 159 | int i; |
159 | 160 | ||
160 | if (!mv88e6352_port_has_serdes(chip, port)) | 161 | if (!mv88e6352_port_has_serdes(chip, port)) |
161 | return; | 162 | return 0; |
162 | 163 | ||
163 | BUILD_BUG_ON(ARRAY_SIZE(mv88e6352_serdes_hw_stats) > | 164 | BUILD_BUG_ON(ARRAY_SIZE(mv88e6352_serdes_hw_stats) > |
164 | ARRAY_SIZE(mv88e6xxx_port->serdes_stats)); | 165 | ARRAY_SIZE(mv88e6xxx_port->serdes_stats)); |
@@ -169,6 +170,8 @@ void mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, | |||
169 | mv88e6xxx_port->serdes_stats[i] += value; | 170 | mv88e6xxx_port->serdes_stats[i] += value; |
170 | data[i] = mv88e6xxx_port->serdes_stats[i]; | 171 | data[i] = mv88e6xxx_port->serdes_stats[i]; |
171 | } | 172 | } |
173 | |||
174 | return ARRAY_SIZE(mv88e6352_serdes_hw_stats); | ||
172 | } | 175 | } |
173 | 176 | ||
174 | /* Set the power on/off for 10GBASE-R and 10GBASE-X4/X2 */ | 177 | /* Set the power on/off for 10GBASE-R and 10GBASE-X4/X2 */ |
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h index 641baa75f910..1897c01c6e19 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.h +++ b/drivers/net/dsa/mv88e6xxx/serdes.h | |||
@@ -45,8 +45,8 @@ | |||
45 | int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on); | 45 | int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on); |
46 | int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on); | 46 | int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on); |
47 | int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port); | 47 | int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port); |
48 | void mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip, | 48 | int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip, |
49 | int port, uint8_t *data); | 49 | int port, uint8_t *data); |
50 | void mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, | 50 | int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, |
51 | uint64_t *data); | 51 | uint64_t *data); |
52 | #endif | 52 | #endif |