diff options
author | Andrew Lunn <andrew@lunn.ch> | 2018-08-09 09:38:49 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-08-09 14:08:20 -0400 |
commit | 734447d4ed7b1f31617c28959fd5adfbd9e39d13 (patch) | |
tree | 7db8f2d5ce4007b17bfcf92083377228202a4a8a | |
parent | efd1ba6af93ff63d40f92515a83405133145c028 (diff) |
net: dsa: mv88e6xxx: Re-setup interrupts on CMODE change.
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>
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/port.c | 19 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/serdes.c | 4 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/serdes.h | 6 |
3 files changed, 27 insertions, 2 deletions
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index 977b4cb82299..92945841c8e8 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c | |||
@@ -342,8 +342,9 @@ int mv88e6390x_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) | |||
342 | int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port, | 342 | int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port, |
343 | phy_interface_t mode) | 343 | phy_interface_t mode) |
344 | { | 344 | { |
345 | u16 reg; | 345 | int lane; |
346 | u16 cmode; | 346 | u16 cmode; |
347 | u16 reg; | ||
347 | int err; | 348 | int err; |
348 | 349 | ||
349 | if (mode == PHY_INTERFACE_MODE_NA) | 350 | if (mode == PHY_INTERFACE_MODE_NA) |
@@ -373,6 +374,16 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port, | |||
373 | cmode = 0; | 374 | cmode = 0; |
374 | } | 375 | } |
375 | 376 | ||
377 | lane = mv88e6390x_serdes_get_lane(chip, port); | ||
378 | if (lane < 0) | ||
379 | return lane; | ||
380 | |||
381 | if (chip->ports[port].serdes_irq) { | ||
382 | err = mv88e6390_serdes_irq_disable(chip, port, lane); | ||
383 | if (err) | ||
384 | return err; | ||
385 | } | ||
386 | |||
376 | err = mv88e6390_serdes_power(chip, port, false); | 387 | err = mv88e6390_serdes_power(chip, port, false); |
377 | if (err) | 388 | if (err) |
378 | return err; | 389 | return err; |
@@ -392,6 +403,12 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port, | |||
392 | err = mv88e6390_serdes_power(chip, port, true); | 403 | err = mv88e6390_serdes_power(chip, port, true); |
393 | if (err) | 404 | if (err) |
394 | return err; | 405 | return err; |
406 | |||
407 | if (chip->ports[port].serdes_irq) { | ||
408 | err = mv88e6390_serdes_irq_enable(chip, port, lane); | ||
409 | if (err) | ||
410 | return err; | ||
411 | } | ||
395 | } | 412 | } |
396 | 413 | ||
397 | chip->ports[port].cmode = cmode; | 414 | chip->ports[port].cmode = cmode; |
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c index 519346b81b87..f007d109b385 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.c +++ b/drivers/net/dsa/mv88e6xxx/serdes.c | |||
@@ -214,7 +214,7 @@ static int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) | |||
214 | * use multiple lanes. If so, return the first lane the port uses. | 214 | * use multiple lanes. If so, return the first lane the port uses. |
215 | * Returns -ENODEV if a port does not have a lane. | 215 | * Returns -ENODEV if a port does not have a lane. |
216 | */ | 216 | */ |
217 | static int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) | 217 | int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) |
218 | { | 218 | { |
219 | u8 cmode_port9, cmode_port10, cmode_port; | 219 | u8 cmode_port9, cmode_port10, cmode_port; |
220 | 220 | ||
@@ -576,6 +576,8 @@ void mv88e6390_serdes_irq_free(struct mv88e6xxx_chip *chip, int port) | |||
576 | mutex_unlock(&chip->reg_lock); | 576 | mutex_unlock(&chip->reg_lock); |
577 | free_irq(chip->ports[port].serdes_irq, &chip->ports[port]); | 577 | free_irq(chip->ports[port].serdes_irq, &chip->ports[port]); |
578 | mutex_lock(&chip->reg_lock); | 578 | mutex_lock(&chip->reg_lock); |
579 | |||
580 | chip->ports[port].serdes_irq = 0; | ||
579 | } | 581 | } |
580 | 582 | ||
581 | int mv88e6341_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on) | 583 | int mv88e6341_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on) |
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h index 09da08cb5261..b1496de9c6fe 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.h +++ b/drivers/net/dsa/mv88e6xxx/serdes.h | |||
@@ -57,6 +57,7 @@ | |||
57 | #define MV88E6390_SGMII_INT_FALSE_CARRIER BIT(7) | 57 | #define MV88E6390_SGMII_INT_FALSE_CARRIER BIT(7) |
58 | #define MV88E6390_SGMII_INT_STATUS 0xa002 | 58 | #define MV88E6390_SGMII_INT_STATUS 0xa002 |
59 | 59 | ||
60 | int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); | ||
60 | int mv88e6341_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on); | 61 | int mv88e6341_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on); |
61 | int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on); | 62 | int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on); |
62 | int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on); | 63 | 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, | |||
68 | int port, uint8_t *data); | 69 | int port, uint8_t *data); |
69 | int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, | 70 | int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, |
70 | uint64_t *data); | 71 | uint64_t *data); |
72 | int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, | ||
73 | int lane); | ||
74 | int mv88e6390_serdes_irq_disable(struct mv88e6xxx_chip *chip, int port, | ||
75 | int lane); | ||
76 | |||
71 | #endif | 77 | #endif |