aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Lunn <andrew@lunn.ch>2018-08-09 09:38:49 -0400
committerDavid S. Miller <davem@davemloft.net>2018-08-09 14:08:20 -0400
commit734447d4ed7b1f31617c28959fd5adfbd9e39d13 (patch)
tree7db8f2d5ce4007b17bfcf92083377228202a4a8a
parentefd1ba6af93ff63d40f92515a83405133145c028 (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.c19
-rw-r--r--drivers/net/dsa/mv88e6xxx/serdes.c4
-rw-r--r--drivers/net/dsa/mv88e6xxx/serdes.h6
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)
342int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port, 342int 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 */
217static int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) 217int 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
581int mv88e6341_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on) 583int 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
60int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
60int mv88e6341_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on); 61int mv88e6341_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on);
61int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on); 62int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on);
62int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on); 63int 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);
69int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, 70int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
70 uint64_t *data); 71 uint64_t *data);
72int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port,
73 int lane);
74int mv88e6390_serdes_irq_disable(struct mv88e6xxx_chip *chip, int port,
75 int lane);
76
71#endif 77#endif