net: dsa: mv88e6xxx: improve 88e6352 serdes statistics detection
authorRussell King (Oracle) <rmk+kernel@armlinux.org.uk>
Thu, 3 Feb 2022 13:30:52 +0000 (13:30 +0000)
committerDavid S. Miller <davem@davemloft.net>
Thu, 3 Feb 2022 14:10:35 +0000 (14:10 +0000)
The decision whether to report serdes statistics currently depends on
the cached C_Mode value for the port, read at probe time or updated by
configuration. However, port 4 can be in "automedia" mode when it is
used as a serdes port, meaning it switches between the internal PHY and
the serdes, changing the read-only C_Mode value depending on which
first gains link. Consequently, the C_Mode value read at probe does not
accurately reflect whether the port has the serdes associated with it.

In "net: dsa: mv88e6xxx: add mv88e6352_g2_scratch_port_has_serdes()",
we added a way to read the hardware configuration to determine which
port has the serdes associated with it. Use this to determine which
port reports the serdes statistics.

Reviewed-by: Marek BehĂșn <kabel@kernel.org>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/dsa/mv88e6xxx/serdes.c

index 2b05ead..6a177bf 100644 (file)
@@ -272,14 +272,6 @@ int mv88e6352_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
        return lane;
 }
 
-static bool mv88e6352_port_has_serdes(struct mv88e6xxx_chip *chip, int port)
-{
-       if (mv88e6xxx_serdes_get_lane(chip, port) >= 0)
-               return true;
-
-       return false;
-}
-
 struct mv88e6352_serdes_hw_stat {
        char string[ETH_GSTRING_LEN];
        int sizeof_stat;
@@ -293,20 +285,24 @@ static struct mv88e6352_serdes_hw_stat mv88e6352_serdes_hw_stats[] = {
 
 int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
 {
-       if (mv88e6352_port_has_serdes(chip, port))
-               return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
+       int err;
 
-       return 0;
+       err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
+       if (err <= 0)
+               return err;
+
+       return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
 }
 
 int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
                                 int port, uint8_t *data)
 {
        struct mv88e6352_serdes_hw_stat *stat;
-       int i;
+       int err, i;
 
-       if (!mv88e6352_port_has_serdes(chip, port))
-               return 0;
+       err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
+       if (err <= 0)
+               return err;
 
        for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) {
                stat = &mv88e6352_serdes_hw_stats[i];
@@ -348,11 +344,12 @@ int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
 {
        struct mv88e6xxx_port *mv88e6xxx_port = &chip->ports[port];
        struct mv88e6352_serdes_hw_stat *stat;
+       int i, err;
        u64 value;
-       int i;
 
-       if (!mv88e6352_port_has_serdes(chip, port))
-               return 0;
+       err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
+       if (err <= 0)
+               return err;
 
        BUILD_BUG_ON(ARRAY_SIZE(mv88e6352_serdes_hw_stats) >
                     ARRAY_SIZE(mv88e6xxx_port->serdes_stats));
@@ -419,8 +416,13 @@ unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
 
 int mv88e6352_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port)
 {
-       if (!mv88e6352_port_has_serdes(chip, port))
-               return 0;
+       int err;
+
+       mv88e6xxx_reg_lock(chip);
+       err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
+       mv88e6xxx_reg_unlock(chip);
+       if (err <= 0)
+               return err;
 
        return 32 * sizeof(u16);
 }
@@ -432,7 +434,8 @@ void mv88e6352_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
        int err;
        int i;
 
-       if (!mv88e6352_port_has_serdes(chip, port))
+       err = mv88e6352_g2_scratch_port_has_serdes(chip, port);
+       if (err <= 0)
                return;
 
        for (i = 0 ; i < 32; i++) {