Skip to content

Commit 0df9528

Browse files
nikita-youshdavem330
authored andcommitted
mv88e6xxx: Add serdes Rx statistics
If packet checker is enabled in the serdes, then Rx counter registers start working, and no side effects have been detected. This patch enables packet checker automatically when powering serdes on, and exposes Rx counter registers via ethtool statistics interface. Code partially basded by older attempt by Andrew Lunn. Signed-off-by: Nikita Yushchenko <[email protected]> Reviewed-by: Andrew Lunn <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent cad451d commit 0df9528

File tree

3 files changed

+109
-3
lines changed

3 files changed

+109
-3
lines changed

drivers/net/dsa/mv88e6xxx/chip.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4424,6 +4424,9 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
44244424
.gpio_ops = &mv88e6352_gpio_ops,
44254425
.avb_ops = &mv88e6390_avb_ops,
44264426
.ptp_ops = &mv88e6352_ptp_ops,
4427+
.serdes_get_sset_count = mv88e6390_serdes_get_sset_count,
4428+
.serdes_get_strings = mv88e6390_serdes_get_strings,
4429+
.serdes_get_stats = mv88e6390_serdes_get_stats,
44274430
.phylink_validate = mv88e6390_phylink_validate,
44284431
};
44294432

drivers/net/dsa/mv88e6xxx/serdes.c

Lines changed: 97 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -405,22 +405,116 @@ static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, u8 lane,
405405
return err;
406406
}
407407

408+
struct mv88e6390_serdes_hw_stat {
409+
char string[ETH_GSTRING_LEN];
410+
int reg;
411+
};
412+
413+
static struct mv88e6390_serdes_hw_stat mv88e6390_serdes_hw_stats[] = {
414+
{ "serdes_rx_pkts", 0xf021 },
415+
{ "serdes_rx_bytes", 0xf024 },
416+
{ "serdes_rx_pkts_error", 0xf027 },
417+
};
418+
419+
int mv88e6390_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
420+
{
421+
if (mv88e6390_serdes_get_lane(chip, port) == 0)
422+
return 0;
423+
424+
return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
425+
}
426+
427+
int mv88e6390_serdes_get_strings(struct mv88e6xxx_chip *chip,
428+
int port, uint8_t *data)
429+
{
430+
struct mv88e6390_serdes_hw_stat *stat;
431+
int i;
432+
433+
if (mv88e6390_serdes_get_lane(chip, port) == 0)
434+
return 0;
435+
436+
for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) {
437+
stat = &mv88e6390_serdes_hw_stats[i];
438+
memcpy(data + i * ETH_GSTRING_LEN, stat->string,
439+
ETH_GSTRING_LEN);
440+
}
441+
return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
442+
}
443+
444+
static uint64_t mv88e6390_serdes_get_stat(struct mv88e6xxx_chip *chip, int lane,
445+
struct mv88e6390_serdes_hw_stat *stat)
446+
{
447+
u16 reg[3];
448+
int err, i;
449+
450+
for (i = 0; i < 3; i++) {
451+
err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
452+
stat->reg + i, &reg[i]);
453+
if (err) {
454+
dev_err(chip->dev, "failed to read statistic\n");
455+
return 0;
456+
}
457+
}
458+
459+
return reg[0] | ((u64)reg[1] << 16) | ((u64)reg[2] << 32);
460+
}
461+
462+
int mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
463+
uint64_t *data)
464+
{
465+
struct mv88e6390_serdes_hw_stat *stat;
466+
int lane;
467+
int i;
468+
469+
lane = mv88e6390_serdes_get_lane(chip, port);
470+
if (lane == 0)
471+
return 0;
472+
473+
for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) {
474+
stat = &mv88e6390_serdes_hw_stats[i];
475+
data[i] = mv88e6390_serdes_get_stat(chip, lane, stat);
476+
}
477+
478+
return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
479+
}
480+
481+
static int mv88e6390_serdes_enable_checker(struct mv88e6xxx_chip *chip, u8 lane)
482+
{
483+
u16 reg;
484+
int err;
485+
486+
err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
487+
MV88E6390_PG_CONTROL, &reg);
488+
if (err)
489+
return err;
490+
491+
reg |= MV88E6390_PG_CONTROL_ENABLE_PC;
492+
return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
493+
MV88E6390_PG_CONTROL, reg);
494+
}
495+
408496
int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane,
409497
bool up)
410498
{
411499
u8 cmode = chip->ports[port].cmode;
500+
int err = 0;
412501

413502
switch (cmode) {
414503
case MV88E6XXX_PORT_STS_CMODE_SGMII:
415504
case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
416505
case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
417-
return mv88e6390_serdes_power_sgmii(chip, lane, up);
506+
err = mv88e6390_serdes_power_sgmii(chip, lane, up);
507+
break;
418508
case MV88E6XXX_PORT_STS_CMODE_XAUI:
419509
case MV88E6XXX_PORT_STS_CMODE_RXAUI:
420-
return mv88e6390_serdes_power_10g(chip, lane, up);
510+
err = mv88e6390_serdes_power_10g(chip, lane, up);
511+
break;
421512
}
422513

423-
return 0;
514+
if (!err && up)
515+
err = mv88e6390_serdes_enable_checker(chip, lane);
516+
517+
return err;
424518
}
425519

426520
static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,

drivers/net/dsa/mv88e6xxx/serdes.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@
7474
#define MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID BIT(11)
7575
#define MV88E6390_SGMII_PHY_STATUS_LINK BIT(10)
7676

77+
/* Packet generator pad packet checker */
78+
#define MV88E6390_PG_CONTROL 0xf010
79+
#define MV88E6390_PG_CONTROL_ENABLE_PC BIT(0)
80+
7781
u8 mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
7882
u8 mv88e6352_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
7983
u8 mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
@@ -99,6 +103,11 @@ int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
99103
int port, uint8_t *data);
100104
int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
101105
uint64_t *data);
106+
int mv88e6390_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port);
107+
int mv88e6390_serdes_get_strings(struct mv88e6xxx_chip *chip,
108+
int port, uint8_t *data);
109+
int mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
110+
uint64_t *data);
102111

103112
/* Return the (first) SERDES lane address a port is using, 0 otherwise. */
104113
static inline u8 mv88e6xxx_serdes_get_lane(struct mv88e6xxx_chip *chip,

0 commit comments

Comments
 (0)