net: dsa: mv88e6xxx: Re-setup interrupts on CMODE change.
authorAndrew Lunn <andrew@lunn.ch>
Thu, 9 Aug 2018 13:38:49 +0000 (15:38 +0200)
committerDavid S. Miller <davem@davemloft.net>
Thu, 9 Aug 2018 18:08:20 +0000 (11:08 -0700)
When a port changes CMODE, the SERDES interface being used can change.
Disable interrupts for the old SERDES interface, and enable interrupts
on the new.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/dsa/mv88e6xxx/port.c
drivers/net/dsa/mv88e6xxx/serdes.c
drivers/net/dsa/mv88e6xxx/serdes.h

index 977b4cb822992cb355cba2595cd3249b1b2c4527..92945841c8e882e0e582372778d5c81603052236 100644 (file)
@@ -342,8 +342,9 @@ int mv88e6390x_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
 int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
                              phy_interface_t mode)
 {
-       u16 reg;
+       int lane;
        u16 cmode;
+       u16 reg;
        int err;
 
        if (mode == PHY_INTERFACE_MODE_NA)
@@ -373,6 +374,16 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
                cmode = 0;
        }
 
+       lane = mv88e6390x_serdes_get_lane(chip, port);
+       if (lane < 0)
+               return lane;
+
+       if (chip->ports[port].serdes_irq) {
+               err = mv88e6390_serdes_irq_disable(chip, port, lane);
+               if (err)
+                       return err;
+       }
+
        err = mv88e6390_serdes_power(chip, port, false);
        if (err)
                return err;
@@ -392,6 +403,12 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
                err = mv88e6390_serdes_power(chip, port, true);
                if (err)
                        return err;
+
+               if (chip->ports[port].serdes_irq) {
+                       err = mv88e6390_serdes_irq_enable(chip, port, lane);
+                       if (err)
+                               return err;
+               }
        }
 
        chip->ports[port].cmode = cmode;
index 519346b81b87176b3bd8c24497f56c40a80a559a..f007d109b3856f8dde333e13970b03f4690a318b 100644 (file)
@@ -214,7 +214,7 @@ static int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
  * use multiple lanes. If so, return the first lane the port uses.
  * Returns -ENODEV if a port does not have a lane.
  */
-static int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
+int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
 {
        u8 cmode_port9, cmode_port10, cmode_port;
 
@@ -576,6 +576,8 @@ void mv88e6390_serdes_irq_free(struct mv88e6xxx_chip *chip, int port)
        mutex_unlock(&chip->reg_lock);
        free_irq(chip->ports[port].serdes_irq, &chip->ports[port]);
        mutex_lock(&chip->reg_lock);
+
+       chip->ports[port].serdes_irq = 0;
 }
 
 int mv88e6341_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
index 09da08cb5261211a5782b7fefbfb74cc08725c01..b1496de9c6fefff42a3c41fdd8c572272cc538f1 100644 (file)
@@ -57,6 +57,7 @@
 #define MV88E6390_SGMII_INT_FALSE_CARRIER      BIT(7)
 #define MV88E6390_SGMII_INT_STATUS     0xa002
 
+int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
 int mv88e6341_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);
@@ -68,4 +69,9 @@ int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
                                 int port, uint8_t *data);
 int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
                               uint64_t *data);
+int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port,
+                               int lane);
+int mv88e6390_serdes_irq_disable(struct mv88e6xxx_chip *chip, int port,
+                                int lane);
+
 #endif