Message ID | 20211117225050.18395-9-kabel@kernel.org (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | Extend `phy-mode` to string array | expand |
On Wed, Nov 17, 2021 at 11:50:50PM +0100, Marek Behún wrote: > +static int mv3310_select_mactype(unsigned long *interfaces) > +{ > + if (test_bit(PHY_INTERFACE_MODE_USXGMII, interfaces)) > + return MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII; > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && > + test_bit(PHY_INTERFACE_MODE_10GBASER, interfaces)) > + return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER; > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && > + test_bit(PHY_INTERFACE_MODE_RXAUI, interfaces)) > + return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI; > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && > + test_bit(PHY_INTERFACE_MODE_XAUI, interfaces)) > + return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI; > + else if (test_bit(PHY_INTERFACE_MODE_10GBASER, interfaces)) > + return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH; > + else if (test_bit(PHY_INTERFACE_MODE_RXAUI, interfaces)) > + return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH; > + else if (test_bit(PHY_INTERFACE_MODE_XAUI, interfaces)) > + return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH; > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces)) > + return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER; Hi, There are differences in the MACTYPE register between the 88X3310 and 88X3340. For example, the 88X3340 has no support for XAUI. This is documented in the data sheet, and in the definitions of these values - note that MV_V2_3310_PORT_CTRL_MACTYPE_XAUI and MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH are only applicable to the 88X3310 (they don't use MV_V2_33X0_*).
Hello, On Wed, Nov 17, 2021 at 11:50:50PM +0100, Marek Behún wrote: > From: Russell King <rmk+kernel@armlinux.org.uk> > > Select the host interface configuration according to the capabilities of > the host. > > This allows the kernel to: > - support SFP modules with 88X33X0 or 88E21X0 inside them > - switch interface modes when the PHY is used with the mvpp2 MAC > (e.g. on MacchiatoBIN) > > Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> > [ rebase, updated, also added support for 88E21X0 ] > Signed-off-by: Marek Behún <kabel@kernel.org> > --- > drivers/net/phy/marvell10g.c | 120 +++++++++++++++++++++++++++++++++-- > 1 file changed, 115 insertions(+), 5 deletions(-) > > diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c > index 0cb9b4ef09c7..94bea1bade6f 100644 > --- a/drivers/net/phy/marvell10g.c > +++ b/drivers/net/phy/marvell10g.c > @@ -96,6 +96,11 @@ enum { > MV_PCS_PORT_INFO_NPORTS_MASK = 0x0380, > MV_PCS_PORT_INFO_NPORTS_SHIFT = 7, > > + /* SerDes reinitialization 88E21X0 */ > + MV_AN_21X0_SERDES_CTRL2 = 0x800f, > + MV_AN_21X0_SERDES_CTRL2_AUTO_INIT_DIS = BIT(13), > + MV_AN_21X0_SERDES_CTRL2_RUN_INIT = BIT(15), > + > /* These registers appear at 0x800X and 0xa00X - the 0xa00X control > * registers appear to set themselves to the 0x800X when AN is > * restarted, but status registers appear readable from either. > @@ -140,6 +145,8 @@ struct mv3310_chip { > bool (*has_downshift)(struct phy_device *phydev); > void (*init_supported_interfaces)(unsigned long *mask); > int (*get_mactype)(struct phy_device *phydev); > + int (*set_mactype)(struct phy_device *phydev, int mactype); > + int (*select_mactype)(unsigned long *interfaces); > int (*init_interface)(struct phy_device *phydev, int mactype); > > #ifdef CONFIG_HWMON > @@ -593,6 +600,49 @@ static int mv2110_get_mactype(struct phy_device *phydev) > return mactype & MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK; > } > > +static int mv2110_set_mactype(struct phy_device *phydev, int mactype) > +{ > + int err, val; > + > + mactype &= MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK; > + err = phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_21X0_PORT_CTRL, > + MV_PMA_21X0_PORT_CTRL_SWRST | > + MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK, > + MV_PMA_21X0_PORT_CTRL_SWRST | mactype); > + if (err) > + return err; > + > + err = phy_set_bits_mmd(phydev, MDIO_MMD_AN, MV_AN_21X0_SERDES_CTRL2, > + MV_AN_21X0_SERDES_CTRL2_AUTO_INIT_DIS | > + MV_AN_21X0_SERDES_CTRL2_RUN_INIT); > + if (err) > + return err; > + > + err = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_AN, > + MV_AN_21X0_SERDES_CTRL2, val, > + !(val & > + MV_AN_21X0_SERDES_CTRL2_RUN_INIT), > + 5000, 100000, true); > + if (err) > + return err; > + > + return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, MV_AN_21X0_SERDES_CTRL2, > + MV_AN_21X0_SERDES_CTRL2_AUTO_INIT_DIS); > +} > + > +static int mv2110_select_mactype(unsigned long *interfaces) > +{ > + if (test_bit(PHY_INTERFACE_MODE_USXGMII, interfaces)) > + return MV_PMA_21X0_PORT_CTRL_MACTYPE_USXGMII; > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && > + !test_bit(PHY_INTERFACE_MODE_10GBASER, interfaces)) > + return MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER; > + else if (test_bit(PHY_INTERFACE_MODE_10GBASER, interfaces)) > + return MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH; > + else > + return -1; > +} > + > static int mv3310_get_mactype(struct phy_device *phydev) > { > int mactype; > @@ -604,6 +654,46 @@ static int mv3310_get_mactype(struct phy_device *phydev) > return mactype & MV_V2_33X0_PORT_CTRL_MACTYPE_MASK; > } > > +static int mv3310_set_mactype(struct phy_device *phydev, int mactype) > +{ > + int ret; > + > + mactype &= MV_V2_33X0_PORT_CTRL_MACTYPE_MASK; > + ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL, > + MV_V2_33X0_PORT_CTRL_MACTYPE_MASK, > + mactype); > + if (ret <= 0) > + return ret; > + > + return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL, > + MV_V2_33X0_PORT_CTRL_SWRST); > +} > + > +static int mv3310_select_mactype(unsigned long *interfaces) > +{ > + if (test_bit(PHY_INTERFACE_MODE_USXGMII, interfaces)) > + return MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII; > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && > + test_bit(PHY_INTERFACE_MODE_10GBASER, interfaces)) > + return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER; > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && > + test_bit(PHY_INTERFACE_MODE_RXAUI, interfaces)) > + return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI; > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && > + test_bit(PHY_INTERFACE_MODE_XAUI, interfaces)) > + return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI; > + else if (test_bit(PHY_INTERFACE_MODE_10GBASER, interfaces)) > + return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH; > + else if (test_bit(PHY_INTERFACE_MODE_RXAUI, interfaces)) > + return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH; > + else if (test_bit(PHY_INTERFACE_MODE_XAUI, interfaces)) > + return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH; > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces)) > + return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER; > + else > + return -1; > +} > + I would like to understand this heuristic better. Both its purpose and its implementation. It says: (a) If the intersection between interface modes supported by the MAC and the PHY contains USXGMII, then use USXGMII as a MACTYPE (b) Otherwise, if the intersection contains both 10GBaseR and SGMII, then use 10GBaseR as MACTYPE (...) (c) Otherwise, if the intersection contains just 10GBaseR (no SGMII), then use 10GBaseR with rate matching as MACTYPE (...) (d) Otherwise, if the intersection contains just SGMII (no 10GBaseR), then use 10GBaseR as MACTYPE (no rate matching). First of all, what is MACTYPE exactly? And what is the purpose of changing it? What would happen if this configuration remained fixed, as it were? I see there is no MACTYPE definition for SGMII. Why is that? How does the PHY choose to use SGMII? Why is item (d) correct - use 10GBaseR as MACTYPE if the intersection only supports SGMII? A breakdown per link speed might be helpful in understanding the configurations being performed here. > static int mv2110_init_interface(struct phy_device *phydev, int mactype) > { > struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); > @@ -674,10 +764,16 @@ static int mv3310_config_init(struct phy_device *phydev) > { > struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); > const struct mv3310_chip *chip = to_mv3310_chip(phydev); > + DECLARE_PHY_INTERFACE_MASK(interfaces); > int err, mactype; > > - /* Check that the PHY interface type is compatible */ > - if (!test_bit(phydev->interface, priv->supported_interfaces)) > + /* In case host didn't provide supported interfaces */ > + __set_bit(phydev->interface, phydev->host_interfaces); Shouldn't phylib populate phydev->host_interfaces with phydev->interface, rather than requiring PHY drivers to do it? > + > + /* Check that there is at least one compatible PHY interface type */ > + phy_interface_and(interfaces, phydev->host_interfaces, > + priv->supported_interfaces); > + if (phy_interface_empty(interfaces)) > return -ENODEV; > > phydev->mdix_ctrl = ETH_TP_MDI_AUTO; > @@ -687,9 +783,15 @@ static int mv3310_config_init(struct phy_device *phydev) > if (err) > return err; > > - mactype = chip->get_mactype(phydev); > - if (mactype < 0) > - return mactype; > + mactype = chip->select_mactype(interfaces); > + if (mactype < 0) { > + mactype = chip->get_mactype(phydev); > + } else { > + phydev_info(phydev, "Changing MACTYPE to %i\n", mactype); > + err = chip->set_mactype(phydev, mactype); > + if (err) > + return err; > + } > > err = chip->init_interface(phydev, mactype); > if (err) { > @@ -1049,6 +1151,8 @@ static const struct mv3310_chip mv3310_type = { > .has_downshift = mv3310_has_downshift, > .init_supported_interfaces = mv3310_init_supported_interfaces, > .get_mactype = mv3310_get_mactype, > + .set_mactype = mv3310_set_mactype, > + .select_mactype = mv3310_select_mactype, > .init_interface = mv3310_init_interface, > > #ifdef CONFIG_HWMON > @@ -1060,6 +1164,8 @@ static const struct mv3310_chip mv3340_type = { > .has_downshift = mv3310_has_downshift, > .init_supported_interfaces = mv3340_init_supported_interfaces, > .get_mactype = mv3310_get_mactype, > + .set_mactype = mv3310_set_mactype, > + .select_mactype = mv3310_select_mactype, > .init_interface = mv3340_init_interface, > > #ifdef CONFIG_HWMON > @@ -1070,6 +1176,8 @@ static const struct mv3310_chip mv3340_type = { > static const struct mv3310_chip mv2110_type = { > .init_supported_interfaces = mv2110_init_supported_interfaces, > .get_mactype = mv2110_get_mactype, > + .set_mactype = mv2110_set_mactype, > + .select_mactype = mv2110_select_mactype, > .init_interface = mv2110_init_interface, > > #ifdef CONFIG_HWMON > @@ -1080,6 +1188,8 @@ static const struct mv3310_chip mv2110_type = { > static const struct mv3310_chip mv2111_type = { > .init_supported_interfaces = mv2111_init_supported_interfaces, > .get_mactype = mv2110_get_mactype, > + .set_mactype = mv2110_set_mactype, > + .select_mactype = mv2110_select_mactype, > .init_interface = mv2110_init_interface, > > #ifdef CONFIG_HWMON > -- > 2.32.0 >
On Thu, Nov 18, 2021 at 02:03:34PM +0200, Vladimir Oltean wrote: > On Wed, Nov 17, 2021 at 11:50:50PM +0100, Marek Behún wrote: > > +static int mv3310_select_mactype(unsigned long *interfaces) > > +{ > > + if (test_bit(PHY_INTERFACE_MODE_USXGMII, interfaces)) > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII; > > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && > > + test_bit(PHY_INTERFACE_MODE_10GBASER, interfaces)) > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER; > > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && > > + test_bit(PHY_INTERFACE_MODE_RXAUI, interfaces)) > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI; > > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && > > + test_bit(PHY_INTERFACE_MODE_XAUI, interfaces)) > > + return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI; > > + else if (test_bit(PHY_INTERFACE_MODE_10GBASER, interfaces)) > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH; > > + else if (test_bit(PHY_INTERFACE_MODE_RXAUI, interfaces)) > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH; > > + else if (test_bit(PHY_INTERFACE_MODE_XAUI, interfaces)) > > + return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH; > > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces)) > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER; > > + else > > + return -1; > > +} > > + > > I would like to understand this heuristic better. Both its purpose and > its implementation. > > It says: > (a) If the intersection between interface modes supported by the MAC and > the PHY contains USXGMII, then use USXGMII as a MACTYPE > (b) Otherwise, if the intersection contains both 10GBaseR and SGMII, then > use 10GBaseR as MACTYPE > (...) > (c) Otherwise, if the intersection contains just 10GBaseR (no SGMII), then > use 10GBaseR with rate matching as MACTYPE > (...) > (d) Otherwise, if the intersection contains just SGMII (no 10GBaseR), then > use 10GBaseR as MACTYPE (no rate matching). What is likely confusing you is a misinterpretation of the constant. MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER actually means the PHY will choose between 10GBASE-R, 5GBASE-R, 2500BASE-X, and SGMII depending on the speed negotiated by the media. In this setting, the PHY dictates which interface mode will be used. I could have named "MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER" as "MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_5GBASER_2500BASEX_SGMII_AUTONEG_ON". Similar with "MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_NO_SGMII_AN", which would be "MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_5GBASER_2500BASEX_SGMII_AUTONEG_OFF". And "MV_V2_3310_PORT_CTRL_MACTYPE_XAUI" would be "MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_5GBASER_2500BASEX_SGMII_AUTONEG_ON". Clearly using such long identifiers would have been rediculous, especially the second one at 74 characters. > First of all, what is MACTYPE exactly? And what is the purpose of > changing it? What would happen if this configuration remained fixed, as > it were? The PHY defines the MAC interface mode depending on the MACTYPE setting selected and the results of the media side negotiation. I think the above answers your remaining questions.
On Thu, 18 Nov 2021 09:41:27 +0000 "Russell King (Oracle)" <linux@armlinux.org.uk> wrote: > On Wed, Nov 17, 2021 at 11:50:50PM +0100, Marek Behún wrote: > > +static int mv3310_select_mactype(unsigned long *interfaces) > > +{ > > + if (test_bit(PHY_INTERFACE_MODE_USXGMII, interfaces)) > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII; > > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && > > + test_bit(PHY_INTERFACE_MODE_10GBASER, interfaces)) > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER; > > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && > > + test_bit(PHY_INTERFACE_MODE_RXAUI, interfaces)) > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI; > > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && > > + test_bit(PHY_INTERFACE_MODE_XAUI, interfaces)) > > + return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI; > > + else if (test_bit(PHY_INTERFACE_MODE_10GBASER, interfaces)) > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH; > > + else if (test_bit(PHY_INTERFACE_MODE_RXAUI, interfaces)) > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH; > > + else if (test_bit(PHY_INTERFACE_MODE_XAUI, interfaces)) > > + return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH; > > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces)) > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER; > > Hi, > > There are differences in the MACTYPE register between the 88X3310 > and 88X3340. For example, the 88X3340 has no support for XAUI. > This is documented in the data sheet, and in the definitions of > these values - note that MV_V2_3310_PORT_CTRL_MACTYPE_XAUI and > MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH are only applicable > to the 88X3310 (they don't use MV_V2_33X0_*). Yes, but 88X3340 does not support XAUI, only RXAUI, it is defined in supported_interfaces. So PHY_INTERFACE_MODE_XAUI will never be set in interfaces, and thus this function can be used for both 88X3310 and 88X3340. Marek
On Thu, 18 Nov 2021 14:03:34 +0200 Vladimir Oltean <olteanv@gmail.com> wrote: > Hello, > > > +static int mv3310_select_mactype(unsigned long *interfaces) > > +{ > > + if (test_bit(PHY_INTERFACE_MODE_USXGMII, interfaces)) > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII; > > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && > > + test_bit(PHY_INTERFACE_MODE_10GBASER, interfaces)) > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER; > > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && > > + test_bit(PHY_INTERFACE_MODE_RXAUI, interfaces)) > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI; > > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && > > + test_bit(PHY_INTERFACE_MODE_XAUI, interfaces)) > > + return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI; > > + else if (test_bit(PHY_INTERFACE_MODE_10GBASER, interfaces)) > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH; > > + else if (test_bit(PHY_INTERFACE_MODE_RXAUI, interfaces)) > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH; > > + else if (test_bit(PHY_INTERFACE_MODE_XAUI, interfaces)) > > + return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH; > > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces)) > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER; > > + else > > + return -1; > > +} > > + > > I would like to understand this heuristic better. Both its purpose and > its implementation. > > It says: > (a) If the intersection between interface modes supported by the MAC and > the PHY contains USXGMII, then use USXGMII as a MACTYPE > (b) Otherwise, if the intersection contains both 10GBaseR and SGMII, then > use 10GBaseR as MACTYPE > (...) > (c) Otherwise, if the intersection contains just 10GBaseR (no SGMII), then > use 10GBaseR with rate matching as MACTYPE > (...) > (d) Otherwise, if the intersection contains just SGMII (no 10GBaseR), then > use 10GBaseR as MACTYPE (no rate matching). > > First of all, what is MACTYPE exactly? And what is the purpose of > changing it? What would happen if this configuration remained fixed, as > it were? > > I see there is no MACTYPE definition for SGMII. Why is that? How does > the PHY choose to use SGMII? > > Why is item (d) correct - use 10GBaseR as MACTYPE if the intersection > only supports SGMII? > > A breakdown per link speed might be helpful in understanding the > configurations being performed here. Russell already explained this. I will put a better explanation into the commit message in v2. > > static int mv2110_init_interface(struct phy_device *phydev, int mactype) > > { > > struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); > > @@ -674,10 +764,16 @@ static int mv3310_config_init(struct phy_device *phydev) > > { > > struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); > > const struct mv3310_chip *chip = to_mv3310_chip(phydev); > > + DECLARE_PHY_INTERFACE_MASK(interfaces); > > int err, mactype; > > > > - /* Check that the PHY interface type is compatible */ > > - if (!test_bit(phydev->interface, priv->supported_interfaces)) > > + /* In case host didn't provide supported interfaces */ > > + __set_bit(phydev->interface, phydev->host_interfaces); > > Shouldn't phylib populate phydev->host_interfaces with > phydev->interface, rather than requiring PHY drivers to do it? I will look into this. Marek
On Thu, Nov 18, 2021 at 01:22:18PM +0000, Russell King (Oracle) wrote: > On Thu, Nov 18, 2021 at 02:03:34PM +0200, Vladimir Oltean wrote: > > On Wed, Nov 17, 2021 at 11:50:50PM +0100, Marek Behún wrote: > > > +static int mv3310_select_mactype(unsigned long *interfaces) > > > +{ > > > + if (test_bit(PHY_INTERFACE_MODE_USXGMII, interfaces)) > > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII; > > > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && > > > + test_bit(PHY_INTERFACE_MODE_10GBASER, interfaces)) > > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER; > > > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && > > > + test_bit(PHY_INTERFACE_MODE_RXAUI, interfaces)) > > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI; > > > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && > > > + test_bit(PHY_INTERFACE_MODE_XAUI, interfaces)) > > > + return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI; > > > + else if (test_bit(PHY_INTERFACE_MODE_10GBASER, interfaces)) > > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH; > > > + else if (test_bit(PHY_INTERFACE_MODE_RXAUI, interfaces)) > > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH; > > > + else if (test_bit(PHY_INTERFACE_MODE_XAUI, interfaces)) > > > + return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH; > > > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces)) > > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER; > > > + else > > > + return -1; > > > +} > > > + > > > > I would like to understand this heuristic better. Both its purpose and > > its implementation. > > > > It says: > > (a) If the intersection between interface modes supported by the MAC and > > the PHY contains USXGMII, then use USXGMII as a MACTYPE > > (b) Otherwise, if the intersection contains both 10GBaseR and SGMII, then > > use 10GBaseR as MACTYPE > > (...) > > (c) Otherwise, if the intersection contains just 10GBaseR (no SGMII), then > > use 10GBaseR with rate matching as MACTYPE > > (...) > > (d) Otherwise, if the intersection contains just SGMII (no 10GBaseR), then > > use 10GBaseR as MACTYPE (no rate matching). > > What is likely confusing you is a misinterpretation of the constant. > MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER actually means the PHY will > choose between 10GBASE-R, 5GBASE-R, 2500BASE-X, and SGMII depending > on the speed negotiated by the media. In this setting, the PHY > dictates which interface mode will be used. > > I could have named "MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER" as > "MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_5GBASER_2500BASEX_SGMII_AUTONEG_ON". > Similar with "MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_NO_SGMII_AN", which > would be > "MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_5GBASER_2500BASEX_SGMII_AUTONEG_OFF". > And "MV_V2_3310_PORT_CTRL_MACTYPE_XAUI" would be > "MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_5GBASER_2500BASEX_SGMII_AUTONEG_ON". > > Clearly using such long identifiers would have been rediculous, > especially the second one at 74 characters. True, but at least there could be a comment above each definition. There's no size limit to that. > > First of all, what is MACTYPE exactly? And what is the purpose of > > changing it? What would happen if this configuration remained fixed, as > > it were? > > The PHY defines the MAC interface mode depending on the MACTYPE > setting selected and the results of the media side negotiation. > > I think the above answers your remaining questions. Ok, so going back to case (d). You said that the full name would be MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_5GBASER_2500BASEX_SGMII_AUTONEG_ON. This means that when the only interface mode supported by the host would be SGMII, the PHY's MACTYPE is still configured to use 2500basex, 5gbaser, 10gbaser for the higher link speeds. Clearly this won't work. But on the other hand, the phylink validate method will remove 2500baseT, 5000baseT, 1000baseT from the advertising mask of the PHY, so the system will never end up operating at those speeds, so it should be fine. The reason why I'm looking at these patches is to see whether they would bring something useful to Aquantia PHYs. These come with firmware on a flash that is customized by Aquantia themselves based on the specifications of a single board. These PHYs have an ability which is very similar to what I'm seeing here, which is to select, for each negotiated link speed on the media side, the SERDES protocol to use on the system side. This is pre-programmed by the firmware, but could be fixed up by the operating system if done carefully. The way Layerscape boards use Aquantia PHYs is to always select the "rate matching" option and keep the SERDES protocol fixed, just configure the mini MAC inside the PHY to emit PAUSE frames towards the system to keep the data rate under control. We would be using these PHYs with the generic C45 driver, which would be mostly enough except for lack of PHY interrupts, because the firmware already configures everything. But on the other hand it gets a bit tiring, especially for PHYs on riser cards, to have to change firmware in order to test a different SERDES protocol, so we were experimenting with some changes in the PHY driver that would basically keep the firmware image fixed, and just fix up the configuration it made, and do things like "use 2500base-x for the 2500base-T speed, and sgmii for 1000base-T/100base-TX". The ability for a PHY to work on a board where its firmware image wasn't specifically designed for it comes in handy sometimes. I was reluctant to submit any changes to the Aquantia PHY driver because we don't really have any guarantees that we wouldn't break any system that uses it. I do know that there are users who do expect SERDES protocol changes currently, because I do see that aqr107_read_status() checks for a possibly modified phydev->interface. But without the ability of knowing what SERDES protocols does the system-side support, it is pretty difficult to modify the SERDES protocol used for a certain link speed without breaking something. I see that this patch set basically introduces the phydev->host_interfaces bitmap which is an attempt to find the answer to that question. But when will we know enough about phydev->host_interfaces in order to safely make decisions in the PHY driver based on it? phylink sets it, phylib does not. And many Aquantia systems use the generic PHY driver, as mentioned. Additionally, there are old device trees at play here, which only define the initial SERDES protocol. Would we be changing the behavior for those, in that we would be configuring the PHY to keep the SERDES protocol fixed whereas it would have dynamically changed before? Another question is what to do if there are multiple ways of establishing a system-side link. For example 1000 Mbps can be achieved either through SGMII, or USXGMII with symbol replication, or 2500base-x with flow control, or 10GBaseR with flow control. And I want to test them all. What would I need to do to change the SERDES protocol from one value to the other? Changing the phy-mode array in the device tree would be one option, but that may not always be possible.
On Thu, Nov 18, 2021 at 02:46:28PM +0100, Marek Behún wrote: > On Thu, 18 Nov 2021 09:41:27 +0000 > "Russell King (Oracle)" <linux@armlinux.org.uk> wrote: > > > On Wed, Nov 17, 2021 at 11:50:50PM +0100, Marek Behún wrote: > > > +static int mv3310_select_mactype(unsigned long *interfaces) > > > +{ > > > + if (test_bit(PHY_INTERFACE_MODE_USXGMII, interfaces)) > > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII; > > > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && > > > + test_bit(PHY_INTERFACE_MODE_10GBASER, interfaces)) > > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER; > > > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && > > > + test_bit(PHY_INTERFACE_MODE_RXAUI, interfaces)) > > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI; > > > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && > > > + test_bit(PHY_INTERFACE_MODE_XAUI, interfaces)) > > > + return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI; > > > + else if (test_bit(PHY_INTERFACE_MODE_10GBASER, interfaces)) > > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH; > > > + else if (test_bit(PHY_INTERFACE_MODE_RXAUI, interfaces)) > > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH; > > > + else if (test_bit(PHY_INTERFACE_MODE_XAUI, interfaces)) > > > + return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH; > > > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces)) > > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER; > > > > Hi, > > > > There are differences in the MACTYPE register between the 88X3310 > > and 88X3340. For example, the 88X3340 has no support for XAUI. > > This is documented in the data sheet, and in the definitions of > > these values - note that MV_V2_3310_PORT_CTRL_MACTYPE_XAUI and > > MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH are only applicable > > to the 88X3310 (they don't use MV_V2_33X0_*). > > Yes, but 88X3340 does not support XAUI, only RXAUI, it is defined in > supported_interfaces. So PHY_INTERFACE_MODE_XAUI will never be set in > interfaces, and thus this function can be used for both 88X3310 and > 88X3340. Okay, that's fine then. The only setting we will omit from this for the 88X3340 then is MV_V2_3340_PORT_CTRL_MACTYPE_RXAUI_NO_SGMII_AN.
On Thu, Nov 18, 2021 at 04:20:39PM +0200, Vladimir Oltean wrote: > On Thu, Nov 18, 2021 at 01:22:18PM +0000, Russell King (Oracle) wrote: > > On Thu, Nov 18, 2021 at 02:03:34PM +0200, Vladimir Oltean wrote: > > > On Wed, Nov 17, 2021 at 11:50:50PM +0100, Marek Behún wrote: > > > > +static int mv3310_select_mactype(unsigned long *interfaces) > > > > +{ > > > > + if (test_bit(PHY_INTERFACE_MODE_USXGMII, interfaces)) > > > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII; > > > > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && > > > > + test_bit(PHY_INTERFACE_MODE_10GBASER, interfaces)) > > > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER; > > > > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && > > > > + test_bit(PHY_INTERFACE_MODE_RXAUI, interfaces)) > > > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI; > > > > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && > > > > + test_bit(PHY_INTERFACE_MODE_XAUI, interfaces)) > > > > + return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI; > > > > + else if (test_bit(PHY_INTERFACE_MODE_10GBASER, interfaces)) > > > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH; > > > > + else if (test_bit(PHY_INTERFACE_MODE_RXAUI, interfaces)) > > > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH; > > > > + else if (test_bit(PHY_INTERFACE_MODE_XAUI, interfaces)) > > > > + return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH; > > > > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces)) > > > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER; > > > > + else > > > > + return -1; > > > > +} > > > > + > > > > > > I would like to understand this heuristic better. Both its purpose and > > > its implementation. > > > > > > It says: > > > (a) If the intersection between interface modes supported by the MAC and > > > the PHY contains USXGMII, then use USXGMII as a MACTYPE > > > (b) Otherwise, if the intersection contains both 10GBaseR and SGMII, then > > > use 10GBaseR as MACTYPE > > > (...) > > > (c) Otherwise, if the intersection contains just 10GBaseR (no SGMII), then > > > use 10GBaseR with rate matching as MACTYPE > > > (...) > > > (d) Otherwise, if the intersection contains just SGMII (no 10GBaseR), then > > > use 10GBaseR as MACTYPE (no rate matching). > > > > What is likely confusing you is a misinterpretation of the constant. > > MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER actually means the PHY will > > choose between 10GBASE-R, 5GBASE-R, 2500BASE-X, and SGMII depending > > on the speed negotiated by the media. In this setting, the PHY > > dictates which interface mode will be used. > > > > I could have named "MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER" as > > "MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_5GBASER_2500BASEX_SGMII_AUTONEG_ON". > > Similar with "MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_NO_SGMII_AN", which > > would be > > "MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_5GBASER_2500BASEX_SGMII_AUTONEG_OFF". > > And "MV_V2_3310_PORT_CTRL_MACTYPE_XAUI" would be > > "MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_5GBASER_2500BASEX_SGMII_AUTONEG_ON". > > > > Clearly using such long identifiers would have been rediculous, > > especially the second one at 74 characters. > > True, but at least there could be a comment above each definition. > There's no size limit to that. > > > > First of all, what is MACTYPE exactly? And what is the purpose of > > > changing it? What would happen if this configuration remained fixed, as > > > it were? > > > > The PHY defines the MAC interface mode depending on the MACTYPE > > setting selected and the results of the media side negotiation. > > > > I think the above answers your remaining questions. > > Ok, so going back to case (d). You said that the full name would be > MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_5GBASER_2500BASEX_SGMII_AUTONEG_ON. > This means that when the only interface mode supported by the host would > be SGMII, the PHY's MACTYPE is still configured to use 2500basex, > 5gbaser, 10gbaser for the higher link speeds. Clearly this won't work. > But on the other hand, the phylink validate method will remove > 2500baseT, 5000baseT, 1000baseT from the advertising mask of the PHY, so > the system will never end up operating at those speeds, so it should be fine. I think you mean 10000baseT rather than 1000baseT. With that correction, you are then correct - with the media restricted to 1G or slower speeds, and the phy in MACTYPE mode 4 (aka 10GBASE-R as the fastest interface mode) it will permanently be talking SGMII to the host. > The reason why I'm looking at these patches is to see whether they would > bring something useful to Aquantia PHYs. These come with firmware on a > flash that is customized by Aquantia themselves based on the specifications > of a single board. These PHYs have an ability which is very similar to > what I'm seeing here, which is to select, for each negotiated link speed > on the media side, the SERDES protocol to use on the system side. This > is pre-programmed by the firmware, but could be fixed up by the > operating system if done carefully. > > The way Layerscape boards use Aquantia PHYs is to always select the > "rate matching" option and keep the SERDES protocol fixed, just > configure the mini MAC inside the PHY to emit PAUSE frames towards the > system to keep the data rate under control. We would be using these PHYs > with the generic C45 driver, which would be mostly enough except for > lack of PHY interrupts, because the firmware already configures > everything. > > But on the other hand it gets a bit tiring, especially for PHYs on riser > cards, to have to change firmware in order to test a different SERDES > protocol, so we were experimenting with some changes in the PHY driver > that would basically keep the firmware image fixed, and just fix up the > configuration it made, and do things like "use 2500base-x for the > 2500base-T speed, and sgmii for 1000base-T/100base-TX". The ability for > a PHY to work on a board where its firmware image wasn't specifically > designed for it comes in handy sometimes. You're going to get into problems with this on Layerscape, because reconfiguring the Serdes etc is something I've tried to highlight as being necessary to NXP since SolidRun started using LX2160A. I think there's some slow progress towards that, but it's so slow that I've basically given up caring about it on the Honeycomb/Clearfog CX boards now. All the SFP cages on my Honeycomb have been configured for the most useful mode to me - 1000BASE-X/SGMII, and I've given up caring about USXGMII/10GBASE-R on those ports. > I see that this patch set basically introduces the phydev->host_interfaces > bitmap which is an attempt to find the answer to that question. But when > will we know enough about phydev->host_interfaces in order to safely > make decisions in the PHY driver based on it? phylink sets it, phylib > does not. It won't be something phylib could set because phylib doesn't know the capabilities of its user - it's information that would need to be provided to phylib. > And many Aquantia systems use the generic PHY driver, as mentioned. > Additionally, there are old device trees at play here, which only define > the initial SERDES protocol. Would we be changing the behavior for those, > in that we would be configuring the PHY to keep the SERDES protocol > fixed whereas it would have dynamically changed before? We have the same situation on Macchiatobin. The 88X3310 there defaults to MACTYPE mode 4, and we've supported this for years with DT describing the interface as 10GBASE-R - because we haven't actually cared very much what DT says up to this point for the 88X3310. As I said in my previous reply, the 88X3310 effectively dictates what the PHY interface mode will be, and that is communicated back through phylib to whoever is using phylib. > Another question is what to do if there are multiple ways of > establishing a system-side link. For example 1000 Mbps can be achieved > either through SGMII, or USXGMII with symbol replication, or 2500base-x > with flow control, or 10GBaseR with flow control. And I want to test > them all. What would I need to do to change the SERDES protocol from one > value to the other? Changing the phy-mode array in the device tree would > be one option, but that may not always be possible. First point to make here is that rate adaption at the PHY is really not well supported in Linux, and there is no way to know via phylib if a PHY is capable or not of rate adaption. Today, if you have a 10GBASE-R link between a PHY doing rate adaption and the "MAC", then what you will get from phylib is: phydev->interface = PHY_INTERFACE_MODE_10GBASER; phydev->speed = SPEED_1000; // result of media negotiation phydev->duplex = DUPLEX_FULL; // result of media negotiation phydev->pause = ...; // result of media negotiation phydev->asym_pause = ...; // result of media negotiation which will, for the majority of implementations, result in the MAC being forced to a 1G speed, possibly with or without pause enabled. Due to this, if phylink is being used, the parameters given to mac_link_up/pcs_link_up will be the result of the media negotiation, not what is required on the actual link. You mention "10GBaseR with flow control" but there is another possibility that exists in real hardware out there. "10GBaseR without flow control" and in that case, the MAC needs to pace its transmission for the media speed (which is a good reason why mac_link_up should be given the result of the media negotiation so it can do transmission pacing.) I have a follow-up to the response I gave to Sean Anderson on rate- adapting PHYs that I need to finish and send, and it would be better to have any discussion on this topic after I've sent that reply and follow-up to that reply.
On Thu, Nov 18, 2021 at 02:47:44PM +0000, Russell King (Oracle) wrote: > On Thu, Nov 18, 2021 at 04:20:39PM +0200, Vladimir Oltean wrote: > > On Thu, Nov 18, 2021 at 01:22:18PM +0000, Russell King (Oracle) wrote: > > > On Thu, Nov 18, 2021 at 02:03:34PM +0200, Vladimir Oltean wrote: > > > > On Wed, Nov 17, 2021 at 11:50:50PM +0100, Marek Behún wrote: > > > > > +static int mv3310_select_mactype(unsigned long *interfaces) > > > > > +{ > > > > > + if (test_bit(PHY_INTERFACE_MODE_USXGMII, interfaces)) > > > > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII; > > > > > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && > > > > > + test_bit(PHY_INTERFACE_MODE_10GBASER, interfaces)) > > > > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER; > > > > > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && > > > > > + test_bit(PHY_INTERFACE_MODE_RXAUI, interfaces)) > > > > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI; > > > > > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && > > > > > + test_bit(PHY_INTERFACE_MODE_XAUI, interfaces)) > > > > > + return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI; > > > > > + else if (test_bit(PHY_INTERFACE_MODE_10GBASER, interfaces)) > > > > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH; > > > > > + else if (test_bit(PHY_INTERFACE_MODE_RXAUI, interfaces)) > > > > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH; > > > > > + else if (test_bit(PHY_INTERFACE_MODE_XAUI, interfaces)) > > > > > + return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH; > > > > > + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces)) > > > > > + return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER; > > > > > + else > > > > > + return -1; > > > > > +} > > > > > + > > > > > > > > I would like to understand this heuristic better. Both its purpose and > > > > its implementation. > > > > > > > > It says: > > > > (a) If the intersection between interface modes supported by the MAC and > > > > the PHY contains USXGMII, then use USXGMII as a MACTYPE > > > > (b) Otherwise, if the intersection contains both 10GBaseR and SGMII, then > > > > use 10GBaseR as MACTYPE > > > > (...) > > > > (c) Otherwise, if the intersection contains just 10GBaseR (no SGMII), then > > > > use 10GBaseR with rate matching as MACTYPE > > > > (...) > > > > (d) Otherwise, if the intersection contains just SGMII (no 10GBaseR), then > > > > use 10GBaseR as MACTYPE (no rate matching). > > > > > > What is likely confusing you is a misinterpretation of the constant. > > > MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER actually means the PHY will > > > choose between 10GBASE-R, 5GBASE-R, 2500BASE-X, and SGMII depending > > > on the speed negotiated by the media. In this setting, the PHY > > > dictates which interface mode will be used. > > > > > > I could have named "MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER" as > > > "MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_5GBASER_2500BASEX_SGMII_AUTONEG_ON". > > > Similar with "MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_NO_SGMII_AN", which > > > would be > > > "MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_5GBASER_2500BASEX_SGMII_AUTONEG_OFF". > > > And "MV_V2_3310_PORT_CTRL_MACTYPE_XAUI" would be > > > "MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_5GBASER_2500BASEX_SGMII_AUTONEG_ON". > > > > > > Clearly using such long identifiers would have been rediculous, > > > especially the second one at 74 characters. > > > > True, but at least there could be a comment above each definition. > > There's no size limit to that. > > > > > > First of all, what is MACTYPE exactly? And what is the purpose of > > > > changing it? What would happen if this configuration remained fixed, as > > > > it were? > > > > > > The PHY defines the MAC interface mode depending on the MACTYPE > > > setting selected and the results of the media side negotiation. > > > > > > I think the above answers your remaining questions. > > > > Ok, so going back to case (d). You said that the full name would be > > MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_5GBASER_2500BASEX_SGMII_AUTONEG_ON. > > This means that when the only interface mode supported by the host would > > be SGMII, the PHY's MACTYPE is still configured to use 2500basex, > > 5gbaser, 10gbaser for the higher link speeds. Clearly this won't work. > > But on the other hand, the phylink validate method will remove > > 2500baseT, 5000baseT, 1000baseT from the advertising mask of the PHY, so > > the system will never end up operating at those speeds, so it should be fine. > > I think you mean 10000baseT rather than 1000baseT. With that correction, > you are then correct - with the media restricted to 1G or slower speeds, > and the phy in MACTYPE mode 4 (aka 10GBASE-R as the fastest interface > mode) it will permanently be talking SGMII to the host. Yes, I missed a zero. > > The reason why I'm looking at these patches is to see whether they would > > bring something useful to Aquantia PHYs. These come with firmware on a > > flash that is customized by Aquantia themselves based on the specifications > > of a single board. These PHYs have an ability which is very similar to > > what I'm seeing here, which is to select, for each negotiated link speed > > on the media side, the SERDES protocol to use on the system side. This > > is pre-programmed by the firmware, but could be fixed up by the > > operating system if done carefully. > > > > The way Layerscape boards use Aquantia PHYs is to always select the > > "rate matching" option and keep the SERDES protocol fixed, just > > configure the mini MAC inside the PHY to emit PAUSE frames towards the > > system to keep the data rate under control. We would be using these PHYs > > with the generic C45 driver, which would be mostly enough except for > > lack of PHY interrupts, because the firmware already configures > > everything. > > > > But on the other hand it gets a bit tiring, especially for PHYs on riser > > cards, to have to change firmware in order to test a different SERDES > > protocol, so we were experimenting with some changes in the PHY driver > > that would basically keep the firmware image fixed, and just fix up the > > configuration it made, and do things like "use 2500base-x for the > > 2500base-T speed, and sgmii for 1000base-T/100base-TX". The ability for > > a PHY to work on a board where its firmware image wasn't specifically > > designed for it comes in handy sometimes. > > You're going to get into problems with this on Layerscape, because > reconfiguring the Serdes etc is something I've tried to highlight > as being necessary to NXP since SolidRun started using LX2160A. I > think there's some slow progress towards that, but it's so slow that > I've basically given up caring about it on the Honeycomb/Clearfog CX > boards now. > > All the SFP cages on my Honeycomb have been configured for the most > useful mode to me - 1000BASE-X/SGMII, and I've given up caring about > USXGMII/10GBASE-R on those ports. Speaking of that, do you know of any SFP modules that would use USXGMII? It doesn't appear to be listed in the spec sheet when looking for that. > > I see that this patch set basically introduces the phydev->host_interfaces > > bitmap which is an attempt to find the answer to that question. But when > > will we know enough about phydev->host_interfaces in order to safely > > make decisions in the PHY driver based on it? phylink sets it, phylib > > does not. > > It won't be something phylib could set because phylib doesn't know > the capabilities of its user - it's information that would need to be > provided to phylib. So you're saying it would be in phylib's best interest to not set it at all, not even to a single bit corresponding to phydev->interface. So PHY drivers could work out this way whether they should operate in backwards compatibility mode or they could change MACTYPE at will. > > And many Aquantia systems use the generic PHY driver, as mentioned. > > Additionally, there are old device trees at play here, which only define > > the initial SERDES protocol. Would we be changing the behavior for those, > > in that we would be configuring the PHY to keep the SERDES protocol > > fixed whereas it would have dynamically changed before? > > We have the same situation on Macchiatobin. The 88X3310 there defaults > to MACTYPE mode 4, and we've supported this for years with DT describing > the interface as 10GBASE-R - because we haven't actually cared very much > what DT says up to this point for the 88X3310. As I said in my previous > reply, the 88X3310 effectively dictates what the PHY interface mode will > be, and that is communicated back through phylib to whoever is using > phylib. So what is the full backwards compatibility strategy with old DT blobs? Is it in this patch set? I didn't notice it. > > Another question is what to do if there are multiple ways of > > establishing a system-side link. For example 1000 Mbps can be achieved > > either through SGMII, or USXGMII with symbol replication, or 2500base-x > > with flow control, or 10GBaseR with flow control. And I want to test > > them all. What would I need to do to change the SERDES protocol from one > > value to the other? Changing the phy-mode array in the device tree would > > be one option, but that may not always be possible. > > First point to make here is that rate adaption at the PHY is really > not well supported in Linux, and there is no way to know via phylib if > a PHY is capable or not of rate adaption. > > Today, if you have a 10GBASE-R link between a PHY doing rate adaption > and the "MAC", then what you will get from phylib is: > > phydev->interface = PHY_INTERFACE_MODE_10GBASER; > phydev->speed = SPEED_1000; // result of media negotiation > phydev->duplex = DUPLEX_FULL; // result of media negotiation > phydev->pause = ...; // result of media negotiation > phydev->asym_pause = ...; // result of media negotiation > > which will, for the majority of implementations, result in the MAC being > forced to a 1G speed, possibly with or without pause enabled. > > Due to this, if phylink is being used, the parameters given to > mac_link_up/pcs_link_up will be the result of the media negotiation, not > what is required on the actual link. > > You mention "10GBaseR with flow control" but there is another > possibility that exists in real hardware out there. "10GBaseR without > flow control" and in that case, the MAC needs to pace its transmission > for the media speed (which is a good reason why mac_link_up should be > given the result of the media negotiation so it can do transmission > pacing.) > > I have a follow-up to the response I gave to Sean Anderson on rate- > adapting PHYs that I need to finish and send, and it would be better > to have any discussion on this topic after I've sent that reply and > follow-up to that reply. Ok, how would the MAC pace itself to send at a lower data rate, if the SERDES protocol is 10G and the PHY doesn't send it PAUSE frames back? At least Layerscape systems can't do this AFAIK. I can watch for updates on this on the other thread.
On Thu, 18 Nov 2021 17:09:51 +0200 Vladimir Oltean <olteanv@gmail.com> wrote: > Speaking of that, do you know of any SFP modules that would use USXGMII? > It doesn't appear to be listed in the spec sheet when looking for that. RollBall 10G SFP modules, which this series prepares support for, contain 88X3310 PHY and thus can work in USXGMII. By defualt they use MACTYPE=6 (10gbase-r with rate matching), but when this series and the series that adds support for RollBall SFPs are merged, then the SFP module will work in USXGMII if USXGMII is supported by the host MAC. Marek
On Thu, Nov 18, 2021 at 05:09:51PM +0200, Vladimir Oltean wrote: > On Thu, Nov 18, 2021 at 02:47:44PM +0000, Russell King (Oracle) wrote: > > You're going to get into problems with this on Layerscape, because > > reconfiguring the Serdes etc is something I've tried to highlight > > as being necessary to NXP since SolidRun started using LX2160A. I > > think there's some slow progress towards that, but it's so slow that > > I've basically given up caring about it on the Honeycomb/Clearfog CX > > boards now. > > > > All the SFP cages on my Honeycomb have been configured for the most > > useful mode to me - 1000BASE-X/SGMII, and I've given up caring about > > USXGMII/10GBASE-R on those ports. > > Speaking of that, do you know of any SFP modules that would use USXGMII? > It doesn't appear to be listed in the spec sheet when looking for that. I only know of one possibility, which is the DM7052 which uses a Broadcom BCM84881 PHY. I believe the PHY is capable of USXGMII (there's various references to it on the 'net) to some extent. By that, I mean it probably does not provide the 16-bit configuration word in USXGMII mode - just like it doesn't provide it in SGMII mode. On the DM7052 module, the PHY is not in USXGMII mode, it will switch interface modes according to the media speed just like the Marvell 88X3310 does. So, it's vital to use the PHY specific driver for this PHY, and not the generic driver. Since the datasheet for the PHY is unavailable, it is not known how to switch it to USXGMII mode, so it may not be possible to do so except by modifying the pin strapping on the PHY. It may be possible to do it through vendor registers. > > > I see that this patch set basically introduces the phydev->host_interfaces > > > bitmap which is an attempt to find the answer to that question. But when > > > will we know enough about phydev->host_interfaces in order to safely > > > make decisions in the PHY driver based on it? phylink sets it, phylib > > > does not. > > > > It won't be something phylib could set because phylib doesn't know > > the capabilities of its user - it's information that would need to be > > provided to phylib. > > So you're saying it would be in phylib's best interest to not set it at > all, not even to a single bit corresponding to phydev->interface. So PHY > drivers could work out this way whether they should operate in backwards > compatibility mode or they could change MACTYPE at will. That's what I'm thinking - if we end up with a single bit set in the host interface, does that mean "the host only supports a single interface type" or does it mean "DT only specified one interface type and we need to operate in backwards compatibility mode". If we provide an empty host_interfaces bitmap, then we can easily detect that it's not set and fallback to compatibility mode - in the case of 88x3310, that would basically mean not attempting to set MACTYPE. > > > And many Aquantia systems use the generic PHY driver, as mentioned. > > > Additionally, there are old device trees at play here, which only define > > > the initial SERDES protocol. Would we be changing the behavior for those, > > > in that we would be configuring the PHY to keep the SERDES protocol > > > fixed whereas it would have dynamically changed before? > > > > We have the same situation on Macchiatobin. The 88X3310 there defaults > > to MACTYPE mode 4, and we've supported this for years with DT describing > > the interface as 10GBASE-R - because we haven't actually cared very much > > what DT says up to this point for the 88X3310. As I said in my previous > > reply, the 88X3310 effectively dictates what the PHY interface mode will > > be, and that is communicated back through phylib to whoever is using > > phylib. > > So what is the full backwards compatibility strategy with old DT blobs? > Is it in this patch set? I didn't notice it. Marek has attempted to create a backwards compatibility in phylink for this. See phylink_update_phy_modes(). > > > Another question is what to do if there are multiple ways of > > > establishing a system-side link. For example 1000 Mbps can be achieved > > > either through SGMII, or USXGMII with symbol replication, or 2500base-x > > > with flow control, or 10GBaseR with flow control. And I want to test > > > them all. What would I need to do to change the SERDES protocol from one > > > value to the other? Changing the phy-mode array in the device tree would > > > be one option, but that may not always be possible. > > > > First point to make here is that rate adaption at the PHY is really > > not well supported in Linux, and there is no way to know via phylib if > > a PHY is capable or not of rate adaption. > > > > Today, if you have a 10GBASE-R link between a PHY doing rate adaption > > and the "MAC", then what you will get from phylib is: > > > > phydev->interface = PHY_INTERFACE_MODE_10GBASER; > > phydev->speed = SPEED_1000; // result of media negotiation > > phydev->duplex = DUPLEX_FULL; // result of media negotiation > > phydev->pause = ...; // result of media negotiation > > phydev->asym_pause = ...; // result of media negotiation > > > > which will, for the majority of implementations, result in the MAC being > > forced to a 1G speed, possibly with or without pause enabled. > > > > Due to this, if phylink is being used, the parameters given to > > mac_link_up/pcs_link_up will be the result of the media negotiation, not > > what is required on the actual link. > > > > You mention "10GBaseR with flow control" but there is another > > possibility that exists in real hardware out there. "10GBaseR without > > flow control" and in that case, the MAC needs to pace its transmission > > for the media speed (which is a good reason why mac_link_up should be > > given the result of the media negotiation so it can do transmission > > pacing.) > > > > I have a follow-up to the response I gave to Sean Anderson on rate- > > adapting PHYs that I need to finish and send, and it would be better > > to have any discussion on this topic after I've sent that reply and > > follow-up to that reply. > > Ok, how would the MAC pace itself to send at a lower data rate, if the > SERDES protocol is 10G and the PHY doesn't send it PAUSE frames back? > At least Layerscape systems can't do this AFAIK. I'm afraid that is an exercise for the reader/MAC driver author since it's dependent on the hardware. One would hope that no one would create a system where the PHY needs to use rate adaption and requires the MAC to pace itself, but the MAC has no way to achieve that. If such a hardware combination exists, I don't see how it could work reliably. However, bear in mind that the 88X3310 on Macchiatobin boards is the one without MACSEC, so if it is configured to only operate at 10GBASE-R with rate adaption, then it will not be generating pause frames and it will expect the MAC to pace. This is about the only platform I have which I could experiment with a PHY performing rate adaption. However, I'm not currently sure how useful that would be - it would be nothing more than an experimentation exercise, and would require MAC pacing to be implemented in the mvpp2 driver.
diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 0cb9b4ef09c7..94bea1bade6f 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -96,6 +96,11 @@ enum { MV_PCS_PORT_INFO_NPORTS_MASK = 0x0380, MV_PCS_PORT_INFO_NPORTS_SHIFT = 7, + /* SerDes reinitialization 88E21X0 */ + MV_AN_21X0_SERDES_CTRL2 = 0x800f, + MV_AN_21X0_SERDES_CTRL2_AUTO_INIT_DIS = BIT(13), + MV_AN_21X0_SERDES_CTRL2_RUN_INIT = BIT(15), + /* These registers appear at 0x800X and 0xa00X - the 0xa00X control * registers appear to set themselves to the 0x800X when AN is * restarted, but status registers appear readable from either. @@ -140,6 +145,8 @@ struct mv3310_chip { bool (*has_downshift)(struct phy_device *phydev); void (*init_supported_interfaces)(unsigned long *mask); int (*get_mactype)(struct phy_device *phydev); + int (*set_mactype)(struct phy_device *phydev, int mactype); + int (*select_mactype)(unsigned long *interfaces); int (*init_interface)(struct phy_device *phydev, int mactype); #ifdef CONFIG_HWMON @@ -593,6 +600,49 @@ static int mv2110_get_mactype(struct phy_device *phydev) return mactype & MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK; } +static int mv2110_set_mactype(struct phy_device *phydev, int mactype) +{ + int err, val; + + mactype &= MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK; + err = phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_21X0_PORT_CTRL, + MV_PMA_21X0_PORT_CTRL_SWRST | + MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK, + MV_PMA_21X0_PORT_CTRL_SWRST | mactype); + if (err) + return err; + + err = phy_set_bits_mmd(phydev, MDIO_MMD_AN, MV_AN_21X0_SERDES_CTRL2, + MV_AN_21X0_SERDES_CTRL2_AUTO_INIT_DIS | + MV_AN_21X0_SERDES_CTRL2_RUN_INIT); + if (err) + return err; + + err = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_AN, + MV_AN_21X0_SERDES_CTRL2, val, + !(val & + MV_AN_21X0_SERDES_CTRL2_RUN_INIT), + 5000, 100000, true); + if (err) + return err; + + return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, MV_AN_21X0_SERDES_CTRL2, + MV_AN_21X0_SERDES_CTRL2_AUTO_INIT_DIS); +} + +static int mv2110_select_mactype(unsigned long *interfaces) +{ + if (test_bit(PHY_INTERFACE_MODE_USXGMII, interfaces)) + return MV_PMA_21X0_PORT_CTRL_MACTYPE_USXGMII; + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && + !test_bit(PHY_INTERFACE_MODE_10GBASER, interfaces)) + return MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER; + else if (test_bit(PHY_INTERFACE_MODE_10GBASER, interfaces)) + return MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH; + else + return -1; +} + static int mv3310_get_mactype(struct phy_device *phydev) { int mactype; @@ -604,6 +654,46 @@ static int mv3310_get_mactype(struct phy_device *phydev) return mactype & MV_V2_33X0_PORT_CTRL_MACTYPE_MASK; } +static int mv3310_set_mactype(struct phy_device *phydev, int mactype) +{ + int ret; + + mactype &= MV_V2_33X0_PORT_CTRL_MACTYPE_MASK; + ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL, + MV_V2_33X0_PORT_CTRL_MACTYPE_MASK, + mactype); + if (ret <= 0) + return ret; + + return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL, + MV_V2_33X0_PORT_CTRL_SWRST); +} + +static int mv3310_select_mactype(unsigned long *interfaces) +{ + if (test_bit(PHY_INTERFACE_MODE_USXGMII, interfaces)) + return MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII; + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && + test_bit(PHY_INTERFACE_MODE_10GBASER, interfaces)) + return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER; + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && + test_bit(PHY_INTERFACE_MODE_RXAUI, interfaces)) + return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI; + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) && + test_bit(PHY_INTERFACE_MODE_XAUI, interfaces)) + return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI; + else if (test_bit(PHY_INTERFACE_MODE_10GBASER, interfaces)) + return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH; + else if (test_bit(PHY_INTERFACE_MODE_RXAUI, interfaces)) + return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH; + else if (test_bit(PHY_INTERFACE_MODE_XAUI, interfaces)) + return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH; + else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces)) + return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER; + else + return -1; +} + static int mv2110_init_interface(struct phy_device *phydev, int mactype) { struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); @@ -674,10 +764,16 @@ static int mv3310_config_init(struct phy_device *phydev) { struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); const struct mv3310_chip *chip = to_mv3310_chip(phydev); + DECLARE_PHY_INTERFACE_MASK(interfaces); int err, mactype; - /* Check that the PHY interface type is compatible */ - if (!test_bit(phydev->interface, priv->supported_interfaces)) + /* In case host didn't provide supported interfaces */ + __set_bit(phydev->interface, phydev->host_interfaces); + + /* Check that there is at least one compatible PHY interface type */ + phy_interface_and(interfaces, phydev->host_interfaces, + priv->supported_interfaces); + if (phy_interface_empty(interfaces)) return -ENODEV; phydev->mdix_ctrl = ETH_TP_MDI_AUTO; @@ -687,9 +783,15 @@ static int mv3310_config_init(struct phy_device *phydev) if (err) return err; - mactype = chip->get_mactype(phydev); - if (mactype < 0) - return mactype; + mactype = chip->select_mactype(interfaces); + if (mactype < 0) { + mactype = chip->get_mactype(phydev); + } else { + phydev_info(phydev, "Changing MACTYPE to %i\n", mactype); + err = chip->set_mactype(phydev, mactype); + if (err) + return err; + } err = chip->init_interface(phydev, mactype); if (err) { @@ -1049,6 +1151,8 @@ static const struct mv3310_chip mv3310_type = { .has_downshift = mv3310_has_downshift, .init_supported_interfaces = mv3310_init_supported_interfaces, .get_mactype = mv3310_get_mactype, + .set_mactype = mv3310_set_mactype, + .select_mactype = mv3310_select_mactype, .init_interface = mv3310_init_interface, #ifdef CONFIG_HWMON @@ -1060,6 +1164,8 @@ static const struct mv3310_chip mv3340_type = { .has_downshift = mv3310_has_downshift, .init_supported_interfaces = mv3340_init_supported_interfaces, .get_mactype = mv3310_get_mactype, + .set_mactype = mv3310_set_mactype, + .select_mactype = mv3310_select_mactype, .init_interface = mv3340_init_interface, #ifdef CONFIG_HWMON @@ -1070,6 +1176,8 @@ static const struct mv3310_chip mv3340_type = { static const struct mv3310_chip mv2110_type = { .init_supported_interfaces = mv2110_init_supported_interfaces, .get_mactype = mv2110_get_mactype, + .set_mactype = mv2110_set_mactype, + .select_mactype = mv2110_select_mactype, .init_interface = mv2110_init_interface, #ifdef CONFIG_HWMON @@ -1080,6 +1188,8 @@ static const struct mv3310_chip mv2110_type = { static const struct mv3310_chip mv2111_type = { .init_supported_interfaces = mv2111_init_supported_interfaces, .get_mactype = mv2110_get_mactype, + .set_mactype = mv2110_set_mactype, + .select_mactype = mv2110_select_mactype, .init_interface = mv2110_init_interface, #ifdef CONFIG_HWMON