From 17deaf5cb37a365fd65aaa0e14d1a2e1a50418c7 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Beh=C3=BAn?= Date: Mon, 26 Aug 2019 23:31:52 +0200 Subject: [PATCH] net: dsa: mv88e6xxx: create serdes_get_lane chip operation MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Create a serdes_get_lane() method in the mv88e6xxx operations structure. Use it instead of calling the different implementations. Also change the methods so that their return value is used only for error. The lane number is put into a place referred to by a pointer given as argument. If the port does not have a lane, return -ENODEV. Lanes are phy addresses, so use u8 as their type. Signed-off-by: Marek Behún Reviewed-by: Vivien Didelot Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 6 + drivers/net/dsa/mv88e6xxx/chip.h | 3 + drivers/net/dsa/mv88e6xxx/port.c | 16 +-- drivers/net/dsa/mv88e6xxx/serdes.c | 197 ++++++++++++++++------------- drivers/net/dsa/mv88e6xxx/serdes.h | 20 ++- 5 files changed, 146 insertions(+), 96 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index ec4274d71145..5a3fff1971b9 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -3255,6 +3255,7 @@ static const struct mv88e6xxx_ops mv88e6190_ops = { .vtu_getnext = mv88e6390_g1_vtu_getnext, .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, .serdes_power = mv88e6390_serdes_power, + .serdes_get_lane = mv88e6390_serdes_get_lane, .serdes_irq_setup = mv88e6390_serdes_irq_setup, .serdes_irq_free = mv88e6390_serdes_irq_free, .gpio_ops = &mv88e6352_gpio_ops, @@ -3301,6 +3302,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = { .vtu_getnext = mv88e6390_g1_vtu_getnext, .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, .serdes_power = mv88e6390x_serdes_power, + .serdes_get_lane = mv88e6390x_serdes_get_lane, .serdes_irq_setup = mv88e6390x_serdes_irq_setup, .serdes_irq_free = mv88e6390x_serdes_irq_free, .gpio_ops = &mv88e6352_gpio_ops, @@ -3347,6 +3349,7 @@ static const struct mv88e6xxx_ops mv88e6191_ops = { .vtu_getnext = mv88e6390_g1_vtu_getnext, .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, .serdes_power = mv88e6390_serdes_power, + .serdes_get_lane = mv88e6390_serdes_get_lane, .serdes_irq_setup = mv88e6390_serdes_irq_setup, .serdes_irq_free = mv88e6390_serdes_irq_free, .avb_ops = &mv88e6390_avb_ops, @@ -3483,6 +3486,7 @@ static const struct mv88e6xxx_ops mv88e6290_ops = { .vtu_getnext = mv88e6390_g1_vtu_getnext, .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, .serdes_power = mv88e6390_serdes_power, + .serdes_get_lane = mv88e6390_serdes_get_lane, .serdes_irq_setup = mv88e6390_serdes_irq_setup, .serdes_irq_free = mv88e6390_serdes_irq_free, .gpio_ops = &mv88e6352_gpio_ops, @@ -3800,6 +3804,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = { .vtu_getnext = mv88e6390_g1_vtu_getnext, .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, .serdes_power = mv88e6390_serdes_power, + .serdes_get_lane = mv88e6390_serdes_get_lane, .serdes_irq_setup = mv88e6390_serdes_irq_setup, .serdes_irq_free = mv88e6390_serdes_irq_free, .gpio_ops = &mv88e6352_gpio_ops, @@ -3850,6 +3855,7 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = { .vtu_getnext = mv88e6390_g1_vtu_getnext, .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, .serdes_power = mv88e6390x_serdes_power, + .serdes_get_lane = mv88e6390x_serdes_get_lane, .serdes_irq_setup = mv88e6390x_serdes_irq_setup, .serdes_irq_free = mv88e6390x_serdes_irq_free, .gpio_ops = &mv88e6352_gpio_ops, diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index a406be2f5652..421e8b84bec3 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -443,6 +443,9 @@ struct mv88e6xxx_ops { /* Power on/off a SERDES interface */ int (*serdes_power)(struct mv88e6xxx_chip *chip, int port, bool on); + /* SERDES lane mapping */ + int (*serdes_get_lane)(struct mv88e6xxx_chip *chip, int port, u8 *lane); + /* SERDES interrupt handling */ int (*serdes_irq_setup)(struct mv88e6xxx_chip *chip, int port); void (*serdes_irq_free)(struct mv88e6xxx_chip *chip, int port); diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index c95cdb73e5a2..4b0c58c30fea 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -395,7 +395,7 @@ phy_interface_t mv88e6390x_port_max_speed_mode(int port) int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port, phy_interface_t mode) { - int lane; + u8 lane; u16 cmode; u16 reg; int err; @@ -434,11 +434,11 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port, if (cmode == chip->ports[port].cmode) return 0; - lane = mv88e6390x_serdes_get_lane(chip, port); - if (lane < 0 && lane != -ENODEV) - return lane; + err = mv88e6xxx_serdes_get_lane(chip, port, &lane); + if (err && err != -ENODEV) + return err; - if (lane >= 0) { + if (err != -ENODEV) { if (chip->ports[port].serdes_irq) { err = mv88e6390_serdes_irq_disable(chip, port, lane); if (err) @@ -466,9 +466,9 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port, chip->ports[port].cmode = cmode; - lane = mv88e6390x_serdes_get_lane(chip, port); - if (lane < 0) - return lane; + err = mv88e6xxx_serdes_get_lane(chip, port, &lane); + if (err) + return err; err = mv88e6390x_serdes_power(chip, port, true); if (err) diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c index 678aaba3d019..e58bccc25b7e 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.c +++ b/drivers/net/dsa/mv88e6xxx/serdes.c @@ -286,10 +286,7 @@ void mv88e6352_serdes_irq_free(struct mv88e6xxx_chip *chip, int port) chip->ports[port].serdes_irq = 0; } -/* Return the SERDES lane address a port is using. Only Ports 9 and 10 - * have SERDES lanes. Returns -ENODEV if a port does not have a lane. - */ -static int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) +int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, u8 *lane) { u8 cmode = chip->ports[port].cmode; @@ -297,25 +294,27 @@ static int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) case 9: if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || - cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) - return MV88E6390_PORT9_LANE0; - return -ENODEV; + cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) { + *lane = MV88E6390_PORT9_LANE0; + return 0; + } + break; case 10: if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || - cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) - return MV88E6390_PORT10_LANE0; - return -ENODEV; + cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) { + *lane = MV88E6390_PORT10_LANE0; + return 0; + } + break; default: - return -ENODEV; + break; } + + return -ENODEV; } -/* Return the SERDES lane address a port is using. Ports 9 and 10 can - * use multiple lanes. If so, return the first lane the port uses. - * Returns -ENODEV if a port does not have a lane. - */ -int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) +int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, u8 *lane) { u8 cmode_port9, cmode_port10, cmode_port; @@ -327,72 +326,96 @@ int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) case 2: if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || - cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX) - if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) - return MV88E6390_PORT9_LANE1; - return -ENODEV; + cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX) { + if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) { + *lane = MV88E6390_PORT9_LANE1; + return 0; + } + } + break; case 3: if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || - cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) - if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) - return MV88E6390_PORT9_LANE2; - return -ENODEV; + cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) { + if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) { + *lane = MV88E6390_PORT9_LANE2; + return 0; + } + } + break; case 4: if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || - cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) - if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) - return MV88E6390_PORT9_LANE3; - return -ENODEV; + cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) { + if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) { + *lane = MV88E6390_PORT9_LANE3; + return 0; + } + } + break; case 5: if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || - cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX) - if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) - return MV88E6390_PORT10_LANE1; - return -ENODEV; + cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX) { + if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) { + *lane = MV88E6390_PORT10_LANE1; + return 0; + } + } + break; case 6: if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || - cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) - if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) - return MV88E6390_PORT10_LANE2; - return -ENODEV; + cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) { + if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) { + *lane = MV88E6390_PORT10_LANE2; + return 0; + } + } + break; case 7: if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || - cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) - if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) - return MV88E6390_PORT10_LANE3; - return -ENODEV; + cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) { + if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) { + *lane = MV88E6390_PORT10_LANE3; + return 0; + } + } + break; case 9: if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || cmode_port9 == MV88E6XXX_PORT_STS_CMODE_XAUI || - cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) - return MV88E6390_PORT9_LANE0; - return -ENODEV; + cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) { + *lane = MV88E6390_PORT9_LANE0; + return 0; + } + break; case 10: if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || cmode_port10 == MV88E6XXX_PORT_STS_CMODE_XAUI || - cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) - return MV88E6390_PORT10_LANE0; - return -ENODEV; + cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) { + *lane = MV88E6390_PORT10_LANE0; + return 0; + } + break; default: - return -ENODEV; + break; } + + return -ENODEV; } /* Set the power on/off for 10GBASE-R and 10GBASE-X4/X2 */ -static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, int lane, +static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, u8 lane, bool on) { u16 val, new_val; @@ -419,7 +442,7 @@ static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, int lane, } /* Set the power on/off for SGMII and 1000Base-X */ -static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, int lane, +static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, u8 lane, bool on) { u16 val, new_val; @@ -445,7 +468,7 @@ static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, int lane, } static int mv88e6390_serdes_power_lane(struct mv88e6xxx_chip *chip, int port, - int lane, bool on) + u8 lane, bool on) { u8 cmode = chip->ports[port].cmode; @@ -464,14 +487,15 @@ static int mv88e6390_serdes_power_lane(struct mv88e6xxx_chip *chip, int port, int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on) { - int lane; - - lane = mv88e6390_serdes_get_lane(chip, port); - if (lane == -ENODEV) - return 0; + u8 lane; + int err; - if (lane < 0) - return lane; + err = mv88e6xxx_serdes_get_lane(chip, port, &lane); + if (err) { + if (err == -ENODEV) + err = 0; + return err; + } switch (port) { case 9 ... 10: @@ -483,14 +507,15 @@ int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on) int mv88e6390x_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on) { - int lane; - - lane = mv88e6390x_serdes_get_lane(chip, port); - if (lane == -ENODEV) - return 0; + u8 lane; + int err; - if (lane < 0) - return lane; + err = mv88e6xxx_serdes_get_lane(chip, port, &lane); + if (err) { + if (err == -ENODEV) + err = 0; + return err; + } switch (port) { case 2 ... 4: @@ -503,7 +528,7 @@ int mv88e6390x_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on) } static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip, - int port, int lane) + int port, u8 lane) { u8 cmode = chip->ports[port].cmode; struct dsa_switch *ds = chip->ds; @@ -570,7 +595,7 @@ static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip, } static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip, - int lane) + u8 lane) { return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, MV88E6390_SGMII_INT_ENABLE, @@ -579,14 +604,14 @@ static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip, } static int mv88e6390_serdes_irq_disable_sgmii(struct mv88e6xxx_chip *chip, - int lane) + u8 lane) { return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, MV88E6390_SGMII_INT_ENABLE, 0); } int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, - int lane) + u8 lane) { u8 cmode = chip->ports[port].cmode; int err = 0; @@ -602,7 +627,7 @@ int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, } int mv88e6390_serdes_irq_disable(struct mv88e6xxx_chip *chip, int port, - int lane) + u8 lane) { u8 cmode = chip->ports[port].cmode; int err = 0; @@ -618,7 +643,7 @@ int mv88e6390_serdes_irq_disable(struct mv88e6xxx_chip *chip, int port, } static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip *chip, - int lane, u16 *status) + u8 lane, u16 *status) { int err; @@ -635,10 +660,10 @@ static irqreturn_t mv88e6390_serdes_thread_fn(int irq, void *dev_id) irqreturn_t ret = IRQ_NONE; u8 cmode = port->cmode; u16 status; - int lane; int err; + u8 lane; - lane = mv88e6390x_serdes_get_lane(chip, port->port); + mv88e6xxx_serdes_get_lane(chip, port->port, &lane); mv88e6xxx_reg_lock(chip); @@ -663,16 +688,15 @@ out: int mv88e6390x_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port) { - int lane; int err; + u8 lane; - lane = mv88e6390x_serdes_get_lane(chip, port); - - if (lane == -ENODEV) - return 0; - - if (lane < 0) - return lane; + err = mv88e6xxx_serdes_get_lane(chip, port, &lane); + if (err) { + if (err == -ENODEV) + err = 0; + return err; + } chip->ports[port].serdes_irq = irq_find_mapping(chip->g2_irq.domain, port); @@ -711,13 +735,16 @@ int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port) void mv88e6390x_serdes_irq_free(struct mv88e6xxx_chip *chip, int port) { - int lane = mv88e6390x_serdes_get_lane(chip, port); - - if (lane == -ENODEV) - return; + int err; + u8 lane; - if (lane < 0) + err = mv88e6xxx_serdes_get_lane(chip, port, &lane); + if (err) { + if (err != -ENODEV) + dev_err(chip->dev, "Unable to free SERDES irq: %d\n", + err); return; + } mv88e6390_serdes_irq_disable(chip, port, lane); diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h index ff5b94439335..959b8cef0b67 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.h +++ b/drivers/net/dsa/mv88e6xxx/serdes.h @@ -74,7 +74,21 @@ #define MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID BIT(11) #define MV88E6390_SGMII_PHY_STATUS_LINK BIT(10) -int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); +/* Put the SERDES lane address a port is using into *lane. If a port has + * multiple lanes, should put the first lane the port is using. If a port does + * not have a lane, return -ENODEV. + */ +static inline int mv88e6xxx_serdes_get_lane(struct mv88e6xxx_chip *chip, + int port, u8 *lane) +{ + if (!chip->info->ops->serdes_get_lane) + return -EOPNOTSUPP; + + return chip->info->ops->serdes_get_lane(chip, port, lane); +} + +int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, u8 *lane); +int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, u8 *lane); 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); @@ -89,9 +103,9 @@ int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip, 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); + u8 lane); int mv88e6390_serdes_irq_disable(struct mv88e6xxx_chip *chip, int port, - int lane); + u8 lane); int mv88e6352_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port); void mv88e6352_serdes_irq_free(struct mv88e6xxx_chip *chip, int port); -- 2.30.2