net: dsa: always use phylink
Subsystems (18)
Russell King (Oracle)
maintainerv2 cover net: dsa: always use phylink
A new revision of the series which incorporates changes that Marek suggested. Specifically, the changes are:
1. Patch 2 - use the phylink_get_caps method in mv88e6xxx to get the default interface rather than re-using port_max_speed_mode()
2. Patch 4 - if no default interface is provided, use the supported interface mask to search for the first interface that gives the fastest speed.
3. Patch 5 - now also removes the port_max_speed_mode() method
drivers/net/dsa/b53/b53_common.c | 3 +- drivers/net/dsa/bcm_sf2.c | 3 +- drivers/net/dsa/hirschmann/hellcreek.c | 3 +- drivers/net/dsa/lantiq_gswip.c | 6 +- drivers/net/dsa/microchip/ksz_common.c | 3 +- drivers/net/dsa/mt7530.c | 3 +- drivers/net/dsa/mv88e6xxx/chip.c | 136 +++++++++++++++--------------- drivers/net/dsa/mv88e6xxx/chip.h | 6 +- drivers/net/dsa/mv88e6xxx/port.c | 32 ------- drivers/net/dsa/mv88e6xxx/port.h | 5 -- drivers/net/dsa/ocelot/felix.c | 3 +- drivers/net/dsa/qca/ar9331.c | 3 +- drivers/net/dsa/qca8k.c | 3 +- drivers/net/dsa/realtek/rtl8365mb.c | 3 +- drivers/net/dsa/sja1105/sja1105_main.c | 3 +- drivers/net/dsa/xrs700x/xrs700x.c | 3 +- drivers/net/phy/phylink.c | 150 ++++++++++++++++++++++++++++++--- include/linux/phylink.h | 5 ++ include/net/dsa.h | 3 +- net/dsa/port.c | 47 +++++++---- 20 files changed, 270 insertions(+), 153 deletions(-)
Quoted 102 lines · Russell King (Oracle)
Mostly the same as the previous RFC, except:
1) incldues the
phylink_validate_mask_caps()function
2) has Marek's idea of searching thesupported_interfacesbitmap for the fastest interface we can use
3) includes a final patch to add a print which will be useful to hear from people testing it.Some of the questions from the original RFC remain though, so I've included that text below. I'm guessing as they remain unanswered that no one has any opinions on them?
drivers/net/dsa/b53/b53_common.c | 3 +- drivers/net/dsa/bcm_sf2.c | 3 +- drivers/net/dsa/hirschmann/hellcreek.c | 3 +- drivers/net/dsa/lantiq_gswip.c | 6 +- drivers/net/dsa/microchip/ksz_common.c | 3 +- drivers/net/dsa/mt7530.c | 3 +- drivers/net/dsa/mv88e6xxx/chip.c | 53 ++++-------- drivers/net/dsa/ocelot/felix.c | 3 +- drivers/net/dsa/qca/ar9331.c | 3 +- drivers/net/dsa/qca8k.c | 3 +- drivers/net/dsa/realtek/rtl8365mb.c | 3 +- drivers/net/dsa/sja1105/sja1105_main.c | 3 +- drivers/net/dsa/xrs700x/xrs700x.c | 3 +- drivers/net/phy/phylink.c | 148 ++++++++++++++++++++++++++++++--- include/linux/phylink.h | 5 ++ include/net/dsa.h | 3 +- net/dsa/port.c | 47 +++++++---- 17 files changed, 215 insertions(+), 80 deletions(-)Quoted 65 lines · Russell King (Oracle)
Hi,
Currently, the core DSA code conditionally uses phylink for CPU and DSA ports depending on whether the firmware specifies a fixed-link or a PHY. If either of these are specified, then phylink is used for these ports, otherwise phylink is not, and we rely on the DSA drivers to "do the right thing". However, this detail is not mentioned in the DT binding, but Andrew has said that this behaviour has always something that DSA wants.
mv88e6xxx has had support for this for a long time with its "
SPEED_MAX" thing, which I recently reworked to make use of themac_capabilitiesin preparation to solving this more fully.This series is an experiment to solve this properly, and it does this in two steps.
The first step consists of the first two patches. Phylink needs to know the PHY interface mode that is being used so it can (a) pass the right mode into the MAC/PCS etc and (b) know the properties of the link and therefore which speeds can be supported across it.
In order to achieve this, the DSA
phylink_get_caps()method has an extra argument added to it so that DSA drivers can report the interface mode that they will be using for this port back to the core DSA code, thereby allowing phylink to be initialised with the correct interface mode.Note that this can only be used for CPU and DSA ports as "user" ports need a different behaviour - they rely on getting the interface mode from phylib, which will only happen if phylink is initialised with
PHY_INTERFACE_MODE_NA. Unfortunately, changing this behaviour is likely to cause widespread regressions.Obvious questions:
1. Shouldphylink_get_caps()be augmented in this way, or should it be a separate method?2. DSA has traditionally used "interface mode for the maximum supported speed on this port" where the interface mode is programmable (via its internal
port_max_speed_mode()method) but this is only present for a few of the sub-drivers. Is reporting the current interface mode correct where this method is not implemented?The second step is to introduce a function that allows phylink to be reconfigured after creation time to operate at max-speed fixed-link mode for the PHY interface mode, also using the MAC capabilities to determine the speed and duplex mode we should be using.
Obvious questions:
1. Should we be allowing half-duplex for this?
2. If we do allow half-duplex, should we prefer fastest speed over duplex setting, or should we prefer fastest full-duplex speed over any half-duplex?
3. How do we sanely switch DSA from its current behaviour to always using phylink for these ports without breakage - this is the difficult one, because it's not obvious which drivers have been coded to either work around this quirk of the DSA implementation. For example, if we start forcing the link down before callingdsa_port_phylink_create(), and we then fail to set max-fixed-link, then the CPU/DSA port is going to fail, and we're going to have lots of regressions.Please look at the patches and make suggestions on how we can proceed to clean up this quirk of DSA.
Signature · 2 lines
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/ FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!
Signature · 2 lines
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/ FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!
RFC PATCH 1/5 net: dsa: add support for retrieving the interface mode
DSA port bindings allow for an optional phy interface mode. When an interface mode is not specified, DSA uses the NA interface mode type.
However, phylink needs to know the parameters of the link, and this will become especially important when using phylink for ports that are devoid of all properties except the required "reg" property, so that phylink can select the maximum supported link settings. Without knowing the interface mode, phylink can't truely know the maximum link speed.
Update the prototype for the phylink_get_caps method to allow drivers to report this information back to DSA, and update all DSA implementations function declarations to cater for this change. No code is added to the implementations.
--- drivers/net/dsa/b53/b53_common.c | 3 ++- drivers/net/dsa/bcm_sf2.c | 3 ++- drivers/net/dsa/hirschmann/hellcreek.c | 3 ++- drivers/net/dsa/lantiq_gswip.c | 6 ++++-- drivers/net/dsa/microchip/ksz_common.c | 3 ++- drivers/net/dsa/mt7530.c | 3 ++- drivers/net/dsa/mv88e6xxx/chip.c | 3 ++- drivers/net/dsa/ocelot/felix.c | 3 ++- drivers/net/dsa/qca/ar9331.c | 3 ++- drivers/net/dsa/qca8k.c | 3 ++- drivers/net/dsa/realtek/rtl8365mb.c | 3 ++- drivers/net/dsa/sja1105/sja1105_main.c | 3 ++- drivers/net/dsa/xrs700x/xrs700x.c | 3 ++- include/net/dsa.h | 3 ++- net/dsa/port.c | 23 +++++++++++++++++------ 15 files changed, 47 insertions(+), 21 deletions(-)
drivers/net/dsa/b53/b53_common.c +2 -1
@@ -1310,7 +1310,8 @@ void b53_port_event(struct dsa_switch *ds, int port)EXPORT_SYMBOL (b53_port_event);static void b53_phylink_get_caps (struct dsa_switch *ds,int port, -struct phylink_config *config) +struct phylink_config *config, +phy_interface_t *default_interface) {struct b53_device *dev = ds->priv;
drivers/net/dsa/bcm_sf2.c +2 -1
@@ -713,7 +713,8 @@ static u32 bcm_sf2_sw_get_phy_flags(struct dsa_switch *ds, int port) }static void bcm_sf2_sw_get_caps (struct dsa_switch *ds,int port, -struct phylink_config *config) +struct phylink_config *config, +phy_interface_t *default_interface) {unsigned long *interfaces = config->supported_interfaces;struct bcm_sf2_priv *priv =bcm_sf2_to_priv (ds);
drivers/net/dsa/hirschmann/hellcreek.c +2 -1
@@ -1462,7 +1462,8 @@ static void hellcreek_teardown(struct dsa_switch *ds) }static void hellcreek_phylink_get_caps (struct dsa_switch *ds,int port, -struct phylink_config *config) +struct phylink_config *config, +phy_interface_t *default_interface) {struct hellcreek *hellcreek = ds->priv;
drivers/net/dsa/lantiq_gswip.c +4 -2
@@ -1492,7 +1492,8 @@ static int gswip_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu) }static void gswip_xrx200_phylink_get_caps (struct dsa_switch *ds,int port, -struct phylink_config *config) +struct phylink_config *config, +phy_interface_t *default_interface) {switch (port) {case 0 :
@@ -1525,7 +1526,8 @@ static void gswip_xrx200_phylink_get_caps(struct dsa_switch *ds, int port, }static void gswip_xrx300_phylink_get_caps (struct dsa_switch *ds,int port, -struct phylink_config *config) +struct phylink_config *config, +phy_interface_t *default_interface) {switch (port) {case 0 :
drivers/net/dsa/microchip/ksz_common.c +2 -1
@@ -721,7 +721,8 @@ static int ksz_check_device_id(struct ksz_device *dev) }static void ksz_phylink_get_caps (struct dsa_switch *ds,int port, -struct phylink_config *config) +struct phylink_config *config, +phy_interface_t *default_interface) {struct ksz_device *dev = ds->priv;
drivers/net/dsa/mt7530.c +2 -1
@@ -2914,7 +2914,8 @@ mt7531_cpu_port_config(struct dsa_switch *ds, int port) }static void mt753x_phylink_get_caps (struct dsa_switch *ds,int port, -struct phylink_config *config) +struct phylink_config *config, +phy_interface_t *default_interface) {struct mt7530_priv *priv = ds->priv;
drivers/net/dsa/mv88e6xxx/chip.c +2 -1
@@ -819,7 +819,8 @@ static void mv88e6393x_phylink_get_caps(struct mv88e6xxx_chip *chip, int port, }static void mv88e6xxx_get_caps (struct dsa_switch *ds,int port, -struct phylink_config *config) +struct phylink_config *config, +phy_interface_t *default_interface) {struct mv88e6xxx_chip *chip = ds->priv;
drivers/net/dsa/ocelot/felix.c +2 -1
@@ -937,7 +937,8 @@ static int felix_vlan_del(struct dsa_switch *ds, int port, }static void felix_phylink_get_caps (struct dsa_switch *ds,int port, -struct phylink_config *config) +struct phylink_config *config, +phy_interface_t *default_interface) {struct ocelot *ocelot = ds->priv;
drivers/net/dsa/qca/ar9331.c +2 -1
@@ -501,7 +501,8 @@ static enum dsa_tag_protocol ar9331_sw_get_tag_protocol(struct dsa_switch *ds, }static void ar9331_sw_phylink_get_caps (struct dsa_switch *ds,int port, -struct phylink_config *config) +struct phylink_config *config, +phy_interface_t *default_interface) { config->mac_capabilities =MAC_ASYM_PAUSE |MAC_SYM_PAUSE |MAC_10 |MAC_100 ;
drivers/net/dsa/qca8k.c +2 -1
@@ -1749,7 +1749,8 @@ qca8k_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode, }static void qca8k_phylink_get_caps (struct dsa_switch *ds,int port, -struct phylink_config *config) +struct phylink_config *config, +phy_interface_t *default_interface) {switch (port) {case 0 :/* 1st CPU port */
drivers/net/dsa/realtek/rtl8365mb.c +2 -1
@@ -1024,7 +1024,8 @@ static int rtl8365mb_ext_config_forcemode(struct realtek_priv *priv, int port, }static void rtl8365mb_phylink_get_caps (struct dsa_switch *ds,int port, -struct phylink_config *config) +struct phylink_config *config, +phy_interface_t *default_interface) {const struct rtl8365mb_extint *extint =rtl8365mb_get_port_extint (ds->priv, port);
drivers/net/dsa/sja1105/sja1105_main.c +2 -1
@@ -1390,7 +1390,8 @@ static void sja1105_mac_link_up(struct dsa_switch *ds, int port, }static void sja1105_phylink_get_caps (struct dsa_switch *ds,int port, -struct phylink_config *config) +struct phylink_config *config, +phy_interface_t *default_interface) {struct sja1105_private *priv = ds->priv;struct sja1105_xmii_params_entry *mii;
drivers/net/dsa/xrs700x/xrs700x.c +2 -1
@@ -443,7 +443,8 @@ static void xrs700x_teardown(struct dsa_switch *ds) }static void xrs700x_phylink_get_caps (struct dsa_switch *ds,int port, -struct phylink_config *config) +struct phylink_config *config, +phy_interface_t *default_interface) {switch (port) {case 0 :
include/net/dsa.h +2 -1
@@ -852,7 +852,8 @@ struct dsa_switch_ops {* PHYLINK integration */ void (*phylink_get_caps)(struct dsa_switch *ds,int port, -struct phylink_config *config); +struct phylink_config *config, +phy_interface_t *default_interface);void (*phylink_validate)(struct dsa_switch *ds,int port,unsigned long *supported,struct phylink_link_state *state);
net/dsa/port.c +17 -6
@@ -1524,13 +1524,9 @@ static const struct phylink_mac_ops dsa_port_phylink_mac_ops = {int dsa_port_phylink_create (struct dsa_port *dp) {struct dsa_switch *ds = dp->ds; -phy_interface_t mode; +phy_interface_t mode, def_mode;int err; - err =of_get_phy_mode (dp->dn, &mode); -if (err) - mode =PHY_INTERFACE_MODE_NA ; -/* Presence of phylink_mac_link_state or phylink_mac_an_restart is * an indicator of a legacy phylink driver. */
@@ -1538,8 +1534,23 @@ int dsa_port_phylink_create(struct dsa_port *dp) ds->ops->phylink_mac_an_restart) dp->pl_config.legacy_pre_march2020 = true; + def_mode =PHY_INTERFACE_MODE_NA ;if (ds->ops->phylink_get_caps) - ds->ops->phylink_get_caps (ds, dp->index, &dp->pl_config); + ds->ops->phylink_get_caps (ds, dp->index, &dp->pl_config, + &def_mode); + + err =of_get_phy_mode (dp->dn, &mode); +if (err) { +/* We must not set the default mode for user ports as a PHY +* overrides the NA mode in phylink. Setting it here would +* prevent the interface mode being updated. +*/ +if (dp->type ==DSA_PORT_TYPE_CPU || + dp->type ==DSA_PORT_TYPE_DSA ) + mode = def_mode; +else + mode =PHY_INTERFACE_MODE_NA ; + } dp->pl =phylink_create (&dp->pl_config,of_fwnode_handle (dp->dn), mode, &dsa_port_phylink_mac_ops);
Signature · 1 line
2.30.2
RFC PATCH 2/5 net: dsa: mv88e6xxx: report the default interface mode for the port
In reply to Russell King (Oracle)Report the maximum speed interface mode for the port, or if we don't have that information, the hardware configured interface mode for the port.
This allows phylink to know which interface mode CPU and DSA ports are operating, which will be necessary when we want to select the maximum speed for the port (required for such ports without a PHY or fixed-link specified in firmware.)
--- drivers/net/dsa/mv88e6xxx/chip.c | 83 +++++++++++++++++++++++--------- drivers/net/dsa/mv88e6xxx/chip.h | 3 +- 2 files changed, 62 insertions(+), 24 deletions(-)
drivers/net/dsa/mv88e6xxx/chip.c +60 -23
@@ -578,7 +578,8 @@ static const u8 mv88e6185_phy_interface_modes[] = { };static void mv88e6095_phylink_get_caps (struct mv88e6xxx_chip *chip,int port, -struct phylink_config *config) +struct phylink_config *config, +phy_interface_t *default_interface) {u8 cmode = chip->ports[port].cmode;
@@ -588,23 +589,29 @@ static void mv88e6095_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,__set_bit (PHY_INTERFACE_MODE_MII , config->supported_interfaces); }else {if (cmode <ARRAY_SIZE (mv88e6185_phy_interface_modes) && - mv88e6185_phy_interface_modes[cmode]) + mv88e6185_phy_interface_modes[cmode]) {__set_bit (mv88e6185_phy_interface_modes[cmode], config->supported_interfaces); + *default_interface = + mv88e6185_phy_interface_modes[cmode]; + } config->mac_capabilities |=MAC_1000FD ; } }static void mv88e6185_phylink_get_caps (struct mv88e6xxx_chip *chip,int port, -struct phylink_config *config) +struct phylink_config *config, +phy_interface_t *default_interface) {u8 cmode = chip->ports[port].cmode;if (cmode <ARRAY_SIZE (mv88e6185_phy_interface_modes) && - mv88e6185_phy_interface_modes[cmode]) + mv88e6185_phy_interface_modes[cmode]) {__set_bit (mv88e6185_phy_interface_modes[cmode], config->supported_interfaces); + *default_interface = mv88e6185_phy_interface_modes[cmode]; + } config->mac_capabilities =MAC_SYM_PAUSE |MAC_10 |MAC_100 |MAC_1000FD ;
@@ -616,6 +623,7 @@ static const u8 mv88e6xxx_phy_interface_modes[] = { [MV88E6XXX_PORT_STS_CMODE_GMII] = PHY_INTERFACE_MODE_GMII, [MV88E6XXX_PORT_STS_CMODE_RMII_PHY] = PHY_INTERFACE_MODE_RMII, [MV88E6XXX_PORT_STS_CMODE_RMII] = PHY_INTERFACE_MODE_RMII, + [MV88E6XXX_PORT_STS_CMODE_RGMII] = PHY_INTERFACE_MODE_RGMII, [MV88E6XXX_PORT_STS_CMODE_100BASEX] = PHY_INTERFACE_MODE_100BASEX, [MV88E6XXX_PORT_STS_CMODE_1000BASEX] = PHY_INTERFACE_MODE_1000BASEX, [MV88E6XXX_PORT_STS_CMODE_SGMII] = PHY_INTERFACE_MODE_SGMII,
@@ -625,22 +633,32 @@ static const u8 mv88e6xxx_phy_interface_modes[] = {*/ }; -static void mv88e6xxx_translate_cmode (u8 cmode,unsigned long *supported) +static void mv88e6xxx_translate_cmode (u8 cmode,unsigned long *supported, +phy_interface_t *default_interface) { +phy_interface_t interface; +if (cmode <ARRAY_SIZE (mv88e6xxx_phy_interface_modes) && - mv88e6xxx_phy_interface_modes[cmode]) -__set_bit (mv88e6xxx_phy_interface_modes[cmode], supported); -else if (cmode ==MV88E6XXX_PORT_STS_CMODE_RGMII ) -phy_interface_set_rgmii (supported); + mv88e6xxx_phy_interface_modes[cmode]) { + interface = mv88e6xxx_phy_interface_modes[cmode]; +if (interface ==PHY_INTERFACE_MODE_RGMII ) +phy_interface_set_rgmii (supported); +else +__set_bit (interface, supported); +if (default_interface) + *default_interface = interface; + } }static void mv88e6250_phylink_get_caps (struct mv88e6xxx_chip *chip,int port, -struct phylink_config *config) +struct phylink_config *config, +phy_interface_t *default_interface) {unsigned long *supported = config->supported_interfaces;/* Translate the default cmode */ -mv88e6xxx_translate_cmode (chip->ports[port].cmode, supported); +mv88e6xxx_translate_cmode (chip->ports[port].cmode, supported, + default_interface); config->mac_capabilities =MAC_SYM_PAUSE |MAC_10 |MAC_100 ; }
@@ -676,13 +694,15 @@ static int mv88e6352_get_port4_serdes_cmode(struct mv88e6xxx_chip *chip) }static void mv88e6352_phylink_get_caps (struct mv88e6xxx_chip *chip,int port, -struct phylink_config *config) +struct phylink_config *config, +phy_interface_t *default_interface) {unsigned long *supported = config->supported_interfaces;int err, cmode;/* Translate the default cmode */ -mv88e6xxx_translate_cmode (chip->ports[port].cmode, supported); +mv88e6xxx_translate_cmode (chip->ports[port].cmode, supported, + default_interface); config->mac_capabilities =MAC_SYM_PAUSE |MAC_10 |MAC_100 |MAC_1000FD ;
@@ -702,19 +722,21 @@ static void mv88e6352_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,dev_err (chip->dev,"p%d: failed to read serdes cmode\n" , port); else -mv88e6xxx_translate_cmode (cmode ,supported ); +mv88e6xxx_translate_cmode (cmode ,supported ,NULL ); unlock:mv88e6xxx_reg_unlock (chip); } }static void mv88e6341_phylink_get_caps (struct mv88e6xxx_chip *chip,int port, -struct phylink_config *config) +struct phylink_config *config, +phy_interface_t *default_interface) {unsigned long *supported = config->supported_interfaces;/* Translate the default cmode */ -mv88e6xxx_translate_cmode (chip->ports[port].cmode, supported); +mv88e6xxx_translate_cmode (chip->ports[port].cmode, supported, + default_interface);/* No ethtool bits for 200Mbps */ config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100 |
@@ -726,17 +748,21 @@ static void mv88e6341_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,__set_bit (PHY_INTERFACE_MODE_1000BASEX , supported);__set_bit (PHY_INTERFACE_MODE_2500BASEX , supported); + *default_interface =PHY_INTERFACE_MODE_2500BASEX ; + config->mac_capabilities |=MAC_2500FD ; } }static void mv88e6390_phylink_get_caps (struct mv88e6xxx_chip *chip,int port, -struct phylink_config *config) +struct phylink_config *config, +phy_interface_t *default_interface) {unsigned long *supported = config->supported_interfaces;/* Translate the default cmode */ -mv88e6xxx_translate_cmode (chip->ports[port].cmode, supported); +mv88e6xxx_translate_cmode (chip->ports[port].cmode, supported, + default_interface);/* No ethtool bits for 200Mbps */ config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100 |
@@ -748,16 +774,19 @@ static void mv88e6390_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,__set_bit (PHY_INTERFACE_MODE_1000BASEX , supported);__set_bit (PHY_INTERFACE_MODE_2500BASEX , supported); + *default_interface =PHY_INTERFACE_MODE_2500BASEX ; + config->mac_capabilities |=MAC_2500FD ; } }static void mv88e6390x_phylink_get_caps (struct mv88e6xxx_chip *chip,int port, -struct phylink_config *config) +struct phylink_config *config, +phy_interface_t *default_interface) {unsigned long *supported = config->supported_interfaces; -mv88e6390_phylink_get_caps (chip, port, config); +mv88e6390_phylink_get_caps (chip, port, config, default_interface);/* For the 6x90X, ports 2-7 can be in automedia mode. * (Note that 6x90 doesn't support RXAUI nor XAUI).
@@ -783,18 +812,22 @@ static void mv88e6390x_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,__set_bit (PHY_INTERFACE_MODE_XAUI , supported);__set_bit (PHY_INTERFACE_MODE_RXAUI , supported); + *default_interface =PHY_INTERFACE_MODE_XAUI ; + config->mac_capabilities |=MAC_10000FD ; } }static void mv88e6393x_phylink_get_caps (struct mv88e6xxx_chip *chip,int port, -struct phylink_config *config) +struct phylink_config *config, +phy_interface_t *default_interface) {unsigned long *supported = config->supported_interfaces;bool is_6191x = chip->info->prod_num ==MV88E6XXX_PORT_SWITCH_ID_PROD_6191X ; -mv88e6xxx_translate_cmode (chip->ports[port].cmode, supported); +mv88e6xxx_translate_cmode (chip->ports[port].cmode, supported, + default_interface); config->mac_capabilities =MAC_SYM_PAUSE |MAC_10 |MAC_100 |MAC_1000FD ;
@@ -812,6 +845,8 @@ static void mv88e6393x_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,/* FIXME: USXGMII is not supported yet */ /* __set_bit(PHY_INTERFACE_MODE_USXGMII, supported); */ + *default_interface =PHY_INTERFACE_MODE_10GBASER ; + config->mac_capabilities |=MAC_2500FD |MAC_5000FD |MAC_10000FD ; }
@@ -823,8 +858,10 @@ static void mv88e6xxx_get_caps(struct dsa_switch *ds, int port, phy_interface_t *default_interface) {struct mv88e6xxx_chip *chip = ds->priv; +u8 cmode = chip->ports[port].cmode; - chip->info->ops->phylink_get_caps (chip, port, config); + chip->info->ops->phylink_get_caps (chip, port, config, + default_interface);/* Internal ports need GMII for PHYLIB */ if (mv88e6xxx_phy_is_internal (ds, port))
drivers/net/dsa/mv88e6xxx/chip.h +2 -1
@@ -643,7 +643,8 @@ struct mv88e6xxx_ops {/* Phylink */ void (*phylink_get_caps)(struct mv88e6xxx_chip *chip,int port, -struct phylink_config *config); +struct phylink_config *config, +phy_interface_t *default_interface);/* Max Frame Size */ int (*set_max_frame_size)(struct mv88e6xxx_chip *chip,int mtu);
Signature · 1 line
2.30.2
Re: [PATCH RFC net-next 2/5] net: dsa: mv88e6xxx: report the default interface mode for the port
Quoted 10 lines · On Tue, 05 Jul 2022 10:47:52 +0100 "Russell King (Oracle)"…
Report the maximum speed interface mode for the port, or if we don't have that information, the hardware configured interface mode for the port.
This allows phylink to know which interface mode CPU and DSA ports are operating, which will be necessary when we want to select the maximum speed for the port (required for such ports without a PHY or fixed-link specified in firmware.)
Signed-off-by Russell King (Oracle) <[email protected]>
kernel test robot
build botRe: [PATCH RFC net-next 2/5] net: dsa: mv88e6xxx: report the default interface mode for the port
In reply to Russell King (Oracle)reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross #…
Hi "Russell,
[FYI, it's a private test report for your RFC patch.] [auto build test WARNING on net-next/master]
url: https://github.com/intel-lab-lkp/linux/commits/Russell-King-Oracle/net-dsa-add-support-for-retrieving-the-interface-mode/20220705-175304 base: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git 874bdbfe624e577687c2053a26aab44715c68453 config: x86_64-randconfig-a012-20220704 (https://download.01.org/0day-ci/archive/20220706/[email protected]/config) compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project f553287b588916de09c66e3e32bf75e5060f967f)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/9423b094f4b1e0c313bbdd0e65cd0824b51e3016
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Russell-King-Oracle/net-dsa-add-support-for-retrieving-the-interface-mode/20220705-175304 git checkout 9423b094f4b1e0c313bbdd0e65cd0824b51e3016
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash drivers/net/dsa/mv88e6xxx/
If you fix the issue, kindly add following tag where applicable
All warnings (new ones prefixed by >>):
>> drivers/net/dsa/mv88e6xxx/chip.c:861:5: warning: unused variable 'cmode' [-Wunused-variable]
u8 cmode = chip->ports[port].cmode;
^1 warning generated.
vim +/cmode +861 drivers/net/dsa/mv88e6xxx/chip.c
855
856 static void mv88e6xxx_get_caps(struct dsa_switch *ds, int port,
857 struct phylink_config *config,
858 phy_interface_t *default_interface)
859 {
860 struct mv88e6xxx_chip *chip = ds->priv;
> 861 u8 cmode = chip->ports[port].cmode;
862
863 chip->info->ops->phylink_get_caps(chip, port, config,
864 default_interface);
865
866 /* Internal ports need GMII for PHYLIB */
867 if (mv88e6xxx_phy_is_internal(ds, port))
868 __set_bit(PHY_INTERFACE_MODE_GMII,
869 config->supported_interfaces);
870 }
871
Signature · 2 lines
0-DAY CI Kernel Test Service https://01.org/lkp
RFC PATCH 3/5 net: phylink: split out interface to caps translation
In reply to Russell King (Oracle)phylink_get_linkmodes() translates the interface mode into a set of speed and duplex capabilities which are masked with the MAC modes to then derive the link modes that are available.
Split out the initial transformation into a new function phylink_interface_to_caps(), which will be useful when setting the maximum fixed link speed.
--- drivers/net/phy/phylink.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-)
drivers/net/phy/phylink.c +19 -12
@@ -296,18 +296,7 @@ static void phylink_caps_to_linkmodes(unsigned long *linkmodes, } } -/** -* phylink_get_linkmodes() - get acceptable link modes -* @linkmodes: ethtool linkmode mask (must be already initialised) -* @interface: phy interface mode defined by &typedef phy_interface_t -* @mac_capabilities: bitmask of MAC capabilities -* -* Set all possible pause, speed and duplex linkmodes in @linkmodes that -* are supported by the @interface mode and @mac_capabilities. @linkmodes -* must have been initialised previously. -*/ -void phylink_get_linkmodes (unsigned long *linkmodes,phy_interface_t interface, -unsigned long mac_capabilities) +static unsigned long phylink_interface_to_caps (phy_interface_t interface) {unsigned long caps =MAC_SYM_PAUSE |MAC_ASYM_PAUSE ;
@@ -381,6 +370,24 @@ void phylink_get_linkmodes(unsigned long *linkmodes, phy_interface_t interface,break ; } +return caps; +} + +/** +* phylink_get_linkmodes() - get acceptable link modes +* @linkmodes: ethtool linkmode mask (must be already initialised) +* @interface: phy interface mode defined by &typedef phy_interface_t +* @mac_capabilities: bitmask of MAC capabilities +* +* Set all possible pause, speed and duplex linkmodes in @linkmodes that +* are supported by the @interface mode and @mac_capabilities. @linkmodes +* must have been initialised previously. +*/ +void phylink_get_linkmodes (unsigned long *linkmodes,phy_interface_t interface, +unsigned long mac_capabilities) +{ +unsigned long caps =phylink_interface_to_caps (interface); +phylink_caps_to_linkmodes (linkmodes, caps & mac_capabilities); }EXPORT_SYMBOL_GPL (phylink_get_linkmodes);
Signature · 1 line
2.30.2
RFC PATCH 4/5 net: phylink: add phylink_set_max_fixed_link()
In reply to Russell King (Oracle)Add a function for DSA to use to configure phylink, in the absence of any other configuration, to a fixed link operating at the maximum supported link speed.
This is needed so we can support phylink usage on CPU and DSA ports.
We use the default interface that the DSA driver provides (if any) otherwise we attempt to find the first supported interface that gives the maximum speed for the link.
--- drivers/net/phy/phylink.c | 119 ++++++++++++++++++++++++++++++++++++++ include/linux/phylink.h | 5 ++ 2 files changed, 124 insertions(+)
drivers/net/phy/phylink.c +119 -0
@@ -1333,6 +1333,125 @@ void phylink_destroy(struct phylink *pl) }EXPORT_SYMBOL_GPL (phylink_destroy); +static struct { +unsigned long fd_mask; +unsigned long hd_mask; +int speed; +} phylink_caps_speeds[] = { + {MAC_400000FD ,0 ,SPEED_400000 }, + {MAC_200000FD ,0 ,SPEED_200000 }, + {MAC_100000FD ,0 ,SPEED_100000 }, + {MAC_56000FD ,0 ,SPEED_56000 }, + {MAC_50000FD ,0 ,SPEED_50000 }, + {MAC_40000FD ,0 ,SPEED_40000 }, + {MAC_25000FD ,0 ,SPEED_40000 }, + {MAC_20000FD ,0 ,SPEED_20000 }, + {MAC_10000FD ,0 ,SPEED_10000 }, + {MAC_5000FD ,0 ,SPEED_5000 }, + {MAC_2500FD ,0 ,SPEED_2500 }, + {MAC_1000FD ,MAC_1000HD ,SPEED_1000 }, + {MAC_100FD ,MAC_100HD ,SPEED_100 }, + {MAC_10FD ,MAC_10HD ,SPEED_10 }, +}; + +/** +* phylink_set_max_fixed_link() - set a fixed link configuration for phylink +* @pl: a pointer to a &struct phylink returned from phylink_create() +* +* Set a maximum speed fixed-link configuration for the chosen interface +* mode and MAC capabilities for the phylink instance. If the interface mode +* is PHY_INTERFACE_MODE_NA, then search the supported interfaces bitmap for +* the first interface that gives the fastest supported speed. +* +* This is only valid for use immediately after phylink_create(). Must not +* be used at any other time. +* +* The user must have initialised mac_capabilities and set a valid interface. +*/ +int phylink_set_max_fixed_link (struct phylink *pl) +{ +phy_interface_t intf, interface; +unsigned long caps, max_caps; +unsigned long *interfaces; +int speed, duplex; +int i; + + interface = pl->link_interface; + +phylink_dbg (pl,"sif=%*pbl if=%d(%s) cap=%lx\n" , + (int )PHY_INTERFACE_MODE_MAX , + pl->config->supported_interfaces, + interface,phy_modes (interface), + pl->config->mac_capabilities); + +/* If we are not in PHY mode, or have a PHY, or have a SFP bus, +* then we must not default to a fixed link. +*/ +if (pl->cfg_link_an_mode !=MLO_AN_PHY || pl->phydev || pl->sfp_bus) +return -EBUSY ; + +if (interface !=PHY_INTERFACE_MODE_NA ) { +/* Get the speed/duplex capabilities and reduce according to the +* specified interface mode. +*/ + caps = pl->config->mac_capabilities; + caps &=phylink_interface_to_caps (interface); + }else { + interfaces = pl->config->supported_interfaces; + max_caps =0 ; + +/* Find the supported interface mode which gives the maximum +* speed. +*/ +for_each_set_bit (intf, interfaces,PHY_INTERFACE_MODE_MAX ) { + caps = pl->config->mac_capabilities; + caps &=phylink_interface_to_caps (intf); +if (caps > max_caps) { + max_caps = caps; + interface = intf; + } + } + + caps = max_caps; + } + + caps &= ~(MAC_SYM_PAUSE |MAC_ASYM_PAUSE ); + +/* If there are no capabilities, then we are not using this default. */ +if (!caps) +return -EINVAL ; + +/* Decode to fastest speed and duplex */ + duplex =DUPLEX_UNKNOWN ; + speed =SPEED_UNKNOWN ; +for (i =0 ; i <ARRAY_SIZE (phylink_caps_speeds); i++) { +if (caps & phylink_caps_speeds[i].fd_mask) { + duplex =DUPLEX_FULL ; + speed = phylink_caps_speeds[i].speed; +break ; + }else if (caps & phylink_caps_speeds[i].hd_mask) { + duplex =DUPLEX_HALF ; + speed = phylink_caps_speeds[i].speed; +break ; + } + } + +/* If we didn't find anything, bail. */ +if (speed ==SPEED_UNKNOWN ) +return -EINVAL ; + + pl->link_interface = interface; + pl->link_config.interface = interface; + pl->link_config.speed = speed; + pl->link_config.duplex = duplex; + pl->link_config.link =1 ; + pl->cfg_link_an_mode =MLO_AN_FIXED ; + pl->cur_link_an_mode =MLO_AN_FIXED ; + +return 0 ; +} +EXPORT_SYMBOL_GPL (phylink_set_max_fixed_link); +static void phylink_phy_change (struct phy_device *phydev,bool up) {struct phylink *pl = phydev->phylink;
include/linux/phylink.h +5 -0
@@ -23,6 +23,9 @@ enum {MAC_SYM_PAUSE =BIT (0 ),MAC_ASYM_PAUSE =BIT (1 ), +/* These speed bits must be sorted according to speed for +* phylink_set_max_fixed_link() +*/ MAC_10HD =BIT (2 ),MAC_10FD =BIT (3 ), MAC_10 = MAC_10HD | MAC_10FD,
@@ -529,6 +532,8 @@ struct phylink *phylink_create(struct phylink_config *, struct fwnode_handle *, const struct phylink_mac_ops *mac_ops);void phylink_destroy (struct phylink *); +int phylink_set_max_fixed_link (struct phylink *pl); +int phylink_connect_phy (struct phylink *,struct phy_device *);int phylink_of_phy_connect (struct phylink *,struct device_node *,u32 flags); int phylink_fwnode_phy_connect(struct phylink *pl,
Signature · 1 line
2.30.2
Re: [PATCH RFC net-next 4/5] net: phylink: add phylink_set_max_fixed_link()
Quoted 11 lines · On Tue, 05 Jul 2022 10:48:02 +0100 "Russell King (Oracle)"…
Add a function for DSA to use to configure phylink, in the absence of any other configuration, to a fixed link operating at the maximum supported link speed.
This is needed so we can support phylink usage on CPU and DSA ports.
We use the default interface that the DSA driver provides (if any) otherwise we attempt to find the first supported interface that gives the maximum speed for the link.
Signed-off-by Russell King (Oracle) <[email protected]>
RFC PATCH 5/5 net: dsa: always use phylink for CPU and DSA ports
In reply to Russell King (Oracle)Currently, we only use phylink for CPU and DSA ports if there is a fixed-link specification, or a PHY specified. The reason for this behaviour is that when neither is specified, there was no way for phylink to know the link parameters.
Now that we have phylink_set_max_link_speed() (which has become possible through the addition of mac_capabilities) we now have the ability to know the maximum link speed for a specific link, and can use phylink for this case as well.
However, we need all DSA drivers to provide mac_capabilities for this to work, and either report the default interface to be used for a port or have filled in supported_interfaces, so that we can select a maximum speed appropriate for the interface mode that hardware may have configured for the port. Any drivers that do not meet these requirements are likely to break.
This is especially important with the conversion of DSA drivers to phylink_pcs, as the PCS code only gets called if we are using phylink for the port.
--- drivers/net/dsa/mv88e6xxx/chip.c | 50 ++++---------------------------- drivers/net/dsa/mv88e6xxx/chip.h | 3 -- drivers/net/dsa/mv88e6xxx/port.c | 32 -------------------- drivers/net/dsa/mv88e6xxx/port.h | 5 ---- net/dsa/port.c | 24 ++++++++------- 5 files changed, 18 insertions(+), 96 deletions(-)
drivers/net/dsa/mv88e6xxx/chip.c +5 -45
@@ -3315,9 +3315,8 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) {struct device_node *phy_handle =NULL ;struct dsa_switch *ds = chip->ds; -phy_interface_t mode;struct dsa_port *dp; -int tx_amp, speed; +int tx_amp;int err;u16 reg;
@@ -3326,40 +3325,10 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) dp =dsa_to_port (ds, port); -/* MAC Forcing register: don't force link, speed, duplex or flow control -* state to any particular values on physical ports, but force the CPU -* port and all DSA ports to their maximum bandwidth and full duplex. -*/ -if (dsa_is_cpu_port (ds, port) ||dsa_is_dsa_port (ds, port)) { -unsigned long caps = dp->pl_config.mac_capabilities; - -if (chip->info->ops->port_max_speed_mode) - mode = chip->info->ops->port_max_speed_mode (port); -else - mode =PHY_INTERFACE_MODE_NA ; - -if (caps &MAC_10000FD ) - speed =SPEED_10000 ; -else if (caps &MAC_5000FD ) - speed =SPEED_5000 ; -else if (caps &MAC_2500FD ) - speed =SPEED_2500 ; -else if (caps &MAC_1000 ) - speed =SPEED_1000 ; -else if (caps &MAC_100 ) - speed =SPEED_100 ; -else - speed =SPEED_10 ; - - err =mv88e6xxx_port_setup_mac (chip, port,LINK_FORCED_UP , - speed,DUPLEX_FULL , -PAUSE_OFF , mode); - }else { - err =mv88e6xxx_port_setup_mac (chip, port,LINK_UNFORCED , -SPEED_UNFORCED ,DUPLEX_UNFORCED , -PAUSE_ON , -PHY_INTERFACE_MODE_NA ); - } + err =mv88e6xxx_port_setup_mac (chip, port,LINK_UNFORCED , +SPEED_UNFORCED ,DUPLEX_UNFORCED , +PAUSE_ON , +PHY_INTERFACE_MODE_NA );if (err)return err;
@@ -4307,7 +4276,6 @@ static const struct mv88e6xxx_ops mv88e6141_ops = { .port_sync_link = mv88e6xxx_port_sync_link, .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, .port_set_speed_duplex = mv88e6341_port_set_speed_duplex, - .port_max_speed_mode = mv88e6341_port_max_speed_mode, .port_tag_remap = mv88e6095_port_tag_remap, .port_set_policy = mv88e6352_port_set_policy, .port_set_frame_mode = mv88e6351_port_set_frame_mode,
@@ -4700,7 +4668,6 @@ static const struct mv88e6xxx_ops mv88e6190_ops = { .port_sync_link = mv88e6xxx_port_sync_link, .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, .port_set_speed_duplex = mv88e6390_port_set_speed_duplex, - .port_max_speed_mode = mv88e6390_port_max_speed_mode, .port_tag_remap = mv88e6390_port_tag_remap, .port_set_policy = mv88e6352_port_set_policy, .port_set_frame_mode = mv88e6351_port_set_frame_mode,
@@ -4763,7 +4730,6 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = { .port_sync_link = mv88e6xxx_port_sync_link, .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, .port_set_speed_duplex = mv88e6390x_port_set_speed_duplex, - .port_max_speed_mode = mv88e6390x_port_max_speed_mode, .port_tag_remap = mv88e6390_port_tag_remap, .port_set_policy = mv88e6352_port_set_policy, .port_set_frame_mode = mv88e6351_port_set_frame_mode,
@@ -4826,7 +4792,6 @@ static const struct mv88e6xxx_ops mv88e6191_ops = { .port_sync_link = mv88e6xxx_port_sync_link, .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, .port_set_speed_duplex = mv88e6390_port_set_speed_duplex, - .port_max_speed_mode = mv88e6390_port_max_speed_mode, .port_tag_remap = mv88e6390_port_tag_remap, .port_set_frame_mode = mv88e6351_port_set_frame_mode, .port_set_ucast_flood = mv88e6352_port_set_ucast_flood,
@@ -4991,7 +4956,6 @@ static const struct mv88e6xxx_ops mv88e6290_ops = { .port_sync_link = mv88e6xxx_port_sync_link, .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, .port_set_speed_duplex = mv88e6390_port_set_speed_duplex, - .port_max_speed_mode = mv88e6390_port_max_speed_mode, .port_tag_remap = mv88e6390_port_tag_remap, .port_set_policy = mv88e6352_port_set_policy, .port_set_frame_mode = mv88e6351_port_set_frame_mode,
@@ -5142,7 +5106,6 @@ static const struct mv88e6xxx_ops mv88e6341_ops = { .port_sync_link = mv88e6xxx_port_sync_link, .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, .port_set_speed_duplex = mv88e6341_port_set_speed_duplex, - .port_max_speed_mode = mv88e6341_port_max_speed_mode, .port_tag_remap = mv88e6095_port_tag_remap, .port_set_policy = mv88e6352_port_set_policy, .port_set_frame_mode = mv88e6351_port_set_frame_mode,
@@ -5365,7 +5328,6 @@ static const struct mv88e6xxx_ops mv88e6390_ops = { .port_sync_link = mv88e6xxx_port_sync_link, .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, .port_set_speed_duplex = mv88e6390_port_set_speed_duplex, - .port_max_speed_mode = mv88e6390_port_max_speed_mode, .port_tag_remap = mv88e6390_port_tag_remap, .port_set_policy = mv88e6352_port_set_policy, .port_set_frame_mode = mv88e6351_port_set_frame_mode,
@@ -5432,7 +5394,6 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = { .port_sync_link = mv88e6xxx_port_sync_link, .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, .port_set_speed_duplex = mv88e6390x_port_set_speed_duplex, - .port_max_speed_mode = mv88e6390x_port_max_speed_mode, .port_tag_remap = mv88e6390_port_tag_remap, .port_set_policy = mv88e6352_port_set_policy, .port_set_frame_mode = mv88e6351_port_set_frame_mode,
@@ -5498,7 +5459,6 @@ static const struct mv88e6xxx_ops mv88e6393x_ops = { .port_sync_link = mv88e6xxx_port_sync_link, .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, .port_set_speed_duplex = mv88e6393x_port_set_speed_duplex, - .port_max_speed_mode = mv88e6393x_port_max_speed_mode, .port_tag_remap = mv88e6390_port_tag_remap, .port_set_policy = mv88e6393x_port_set_policy, .port_set_frame_mode = mv88e6351_port_set_frame_mode,
drivers/net/dsa/mv88e6xxx/chip.h +0 -3
@@ -502,9 +502,6 @@ struct mv88e6xxx_ops {int (*port_set_speed_duplex)(struct mv88e6xxx_chip *chip,int port,int speed,int duplex); -/* What interface mode should be used for maximum speed? */ -phy_interface_t (*port_max_speed_mode)(int port); -int (*port_tag_remap)(struct mv88e6xxx_chip *chip,int port); int (*port_set_policy)(struct mv88e6xxx_chip *chip, int port,
drivers/net/dsa/mv88e6xxx/port.c +0 -32
@@ -333,14 +333,6 @@ int mv88e6341_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port, duplex); } -phy_interface_t mv88e6341_port_max_speed_mode (int port) -{ -if (port ==5 ) -return PHY_INTERFACE_MODE_2500BASEX ; - -return PHY_INTERFACE_MODE_NA ; -} -/* Support 10, 100, 200, 1000 Mbps (e.g. 88E6352 family) */ int mv88e6352_port_set_speed_duplex (struct mv88e6xxx_chip *chip,int port,int speed,int duplex)
@@ -372,14 +364,6 @@ int mv88e6390_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port, duplex); } -phy_interface_t mv88e6390_port_max_speed_mode (int port) -{ -if (port ==9 || port ==10 ) -return PHY_INTERFACE_MODE_2500BASEX ; - -return PHY_INTERFACE_MODE_NA ; -} -/* Support 10, 100, 200, 1000, 2500, 10000 Mbps (e.g. 88E6190X) */ int mv88e6390x_port_set_speed_duplex (struct mv88e6xxx_chip *chip,int port,int speed,int duplex)
@@ -394,14 +378,6 @@ int mv88e6390x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port, duplex); } -phy_interface_t mv88e6390x_port_max_speed_mode (int port) -{ -if (port ==9 || port ==10 ) -return PHY_INTERFACE_MODE_XAUI ; - -return PHY_INTERFACE_MODE_NA ; -} -/* Support 10, 100, 200, 1000, 2500, 5000, 10000 Mbps (e.g. 88E6393X) * Function mv88e6xxx_port_set_speed_duplex() can't be used as the register * values for speeds 2500 & 5000 conflict.
@@ -491,14 +467,6 @@ int mv88e6393x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,return 0 ; } -phy_interface_t mv88e6393x_port_max_speed_mode (int port) -{ -if (port ==0 || port ==9 || port ==10 ) -return PHY_INTERFACE_MODE_10GBASER ; - -return PHY_INTERFACE_MODE_NA ; -} -static int mv88e6xxx_port_set_cmode (struct mv88e6xxx_chip *chip,int port,phy_interface_t mode,bool force) {
drivers/net/dsa/mv88e6xxx/port.h +0 -5
@@ -357,11 +357,6 @@ int mv88e6390x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,int mv88e6393x_port_set_speed_duplex (struct mv88e6xxx_chip *chip,int port,int speed,int duplex); -phy_interface_t mv88e6341_port_max_speed_mode (int port); -phy_interface_t mv88e6390_port_max_speed_mode (int port); -phy_interface_t mv88e6390x_port_max_speed_mode (int port); -phy_interface_t mv88e6393x_port_max_speed_mode (int port); -int mv88e6xxx_port_set_state (struct mv88e6xxx_chip *chip,int port,u8 state);int mv88e6xxx_port_set_vlan_map (struct mv88e6xxx_chip *chip,int port,u16 map);
net/dsa/port.c +13 -11
@@ -1525,6 +1525,7 @@ int dsa_port_phylink_create(struct dsa_port *dp) {struct dsa_switch *ds = dp->ds;phy_interface_t mode, def_mode; +struct device_node *phy_np;int err;/* Presence of phylink_mac_link_state or phylink_mac_an_restart is
@@ -1559,6 +1560,13 @@ int dsa_port_phylink_create(struct dsa_port *dp)return PTR_ERR (dp->pl); } +if (dp->type ==DSA_PORT_TYPE_CPU || dp->type ==DSA_PORT_TYPE_DSA ) { + phy_np =of_parse_phandle (dp->dn,"phy-handle" ,0 ); +of_node_put (phy_np); +if (!phy_np) + err =phylink_set_max_fixed_link (dp->pl); + } +return 0 ; }
@@ -1663,20 +1671,14 @@ static int dsa_port_phylink_register(struct dsa_port *dp)int dsa_port_link_register_of (struct dsa_port *dp) {struct dsa_switch *ds = dp->ds; -struct device_node *phy_np;int port = dp->index;if (!ds->ops->adjust_link) { - phy_np =of_parse_phandle (dp->dn,"phy-handle" ,0 ); -if (of_phy_is_fixed_link (dp->dn) || phy_np) { -if (ds->ops->phylink_mac_link_down) - ds->ops->phylink_mac_link_down (ds, port, -MLO_AN_FIXED ,PHY_INTERFACE_MODE_NA ); -of_node_put (phy_np); -return dsa_port_phylink_register (dp); - } -of_node_put (phy_np); -return 0 ; +if (ds->ops->phylink_mac_link_down) + ds->ops->phylink_mac_link_down (ds, port, +MLO_AN_FIXED ,PHY_INTERFACE_MODE_NA ); + +return dsa_port_phylink_register (dp); } dev_warn(ds->dev,
Signature · 1 line
2.30.2
Vladimir Oltean
maintainerRe: [PATCH RFC net-next 5/5] net: dsa: always use phylink for CPU and DSA ports
Hello,
Quoted 13 lines · Russell King (Oracle)
net/dsa/port.c +1
-0@@ -1525,6 +1525,7 @@ int dsa_port_phylink_create(struct dsa_port *dp) {struct dsa_switch *ds = dp->ds;phy_interface_t mode, def_mode; +struct device_node *phy_np;int err;/* Presence of phylink_mac_link_state or phylink_mac_an_restart is
net/dsa/port.c int dsa_port_phylink_create(struct dsa_port *dp) · line 1567
Quoted 8 lines
net/dsa/port.c +5
-0@@ -1559,6 +1560,13 @@ int dsa_port_phylink_create(struct dsa_port *dp)return PTR_ERR (dp->pl); } +if (dp->type ==DSA_PORT_TYPE_CPU || dp->type ==DSA_PORT_TYPE_DSA ) { + phy_np =of_parse_phandle (dp->dn,"phy-handle" ,0 ); +of_node_put (phy_np); +if (!phy_np) + err =phylink_set_max_fixed_link (dp->pl);
Can we please limit phylink_set_max_link_speed() to just the CPU ports where a fixed-link property is also missing, not just a phy-handle? Although to be entirely correct, we can also have MLO_AN_INBAND, which wouldn't be covered by these 2 checks and would still represent a valid DT binding.
Quoted 16 lines
net/dsa/port.c +2
-4+ } +return 0 ; }@@ -1663,20 +1671,14 @@ static int dsa_port_phylink_register(struct dsa_port *dp)int dsa_port_link_register_of (struct dsa_port *dp) {struct dsa_switch *ds = dp->ds; -struct device_node *phy_np;int port = dp->index;if (!ds->ops->adjust_link) { - phy_np =of_parse_phandle (dp->dn,"phy-handle" ,0 ); -if (of_phy_is_fixed_link (dp->dn) || phy_np) { -if (ds->ops->phylink_mac_link_down)
net/dsa/port.c static int dsa_port_phylink_register(struct dsa_port *dp) · line 1679
Quoted 10 lines
net/dsa/port.c +3
-7- ds->ops->phylink_mac_link_down (ds, port, -MLO_AN_FIXED ,PHY_INTERFACE_MODE_NA ); -of_node_put (phy_np); -return dsa_port_phylink_register (dp); - } -of_node_put (phy_np); -return 0 ; +if (ds->ops->phylink_mac_link_down) + ds->ops->phylink_mac_link_down (ds, port, +MLO_AN_FIXED ,PHY_INTERFACE_MODE_NA );
Can you please align these arguments to the open bracket?
Quoted 8 lines
net/dsa/port.c +2
-0+ +return dsa_port_phylink_register (dp); } dev_warn(ds->dev,Signature · 1 line
2.30.2
Russell King (Oracle)
maintainerRe: [PATCH RFC net-next 5/5] net: dsa: always use phylink for CPU and DSA ports
Quoted 19 lines · Vladimir Oltean
Hello,
Quoted 16 lines · Russell King (Oracle)
net/dsa/port.c +1
-0@@ -1525,6 +1525,7 @@ int dsa_port_phylink_create(struct dsa_port *dp) {struct dsa_switch *ds = dp->ds;phy_interface_t mode, def_mode; +struct device_node *phy_np;int err;/* Presence of phylink_mac_link_state or phylink_mac_an_restart is @@ -1559,6 +1560,13 @@ int dsa_port_phylink_create(struct dsa_port *dp)return PTR_ERR (dp->pl); }
Quoted 11 lines
net/dsa/port.c int dsa_port_phylink_create(struct dsa_port *dp) · line 1567
Quoted 5 lines
net/dsa/port.c +5
-0+if (dp->type ==DSA_PORT_TYPE_CPU || dp->type ==DSA_PORT_TYPE_DSA ) { + phy_np =of_parse_phandle (dp->dn,"phy-handle" ,0 ); +of_node_put (phy_np); +if (!phy_np) + err =phylink_set_max_fixed_link (dp->pl);Can we please limit
phylink_set_max_link_speed()to just the CPU ports where a fixed-link property is also missing, not just a phy-handle? Although to be entirely correct, we can also haveMLO_AN_INBAND, which wouldn't be covered by these 2 checks and would still represent a valid DT binding.
phylink_set_max_fixed_link() already excludes itself:
if (pl->cfg_link_an_mode != MLO_AN_PHY || pl->phydev || pl->sfp_bus)
return -EBUSY;intentionally so that if there is anything specified for the port, be that a fixed link or in-band, then phylink_set_max_fixed_link() errors out with -EBUSY.
The only case that it can't detect is if there is a PHY that may be added to phylink at a later time, and that is what the check above is for.
Signature · 2 lines
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/ FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!
Russell King (Oracle)
maintainerRe: [PATCH RFC net-next 5/5] net: dsa: always use phylink for CPU and DSA ports
Quoted 12 lines · Russell King (Oracle)
Quoted 5 lines · Vladimir Oltean
Can we please limit
phylink_set_max_link_speed()to just the CPU ports where a fixed-link property is also missing, not just a phy-handle? Although to be entirely correct, we can also haveMLO_AN_INBAND, which wouldn't be covered by these 2 checks and would still represent a valid DT binding.
phylink_set_max_fixed_link()already excludes itself:if (pl->cfg_link_an_mode != MLO_AN_PHY || pl->phydev || pl->sfp_bus) return -EBUSY;
Quoted 7 lines
intentionally so that if there is anything specified for the port, be that a fixed link or in-band, then
phylink_set_max_fixed_link()errors out with-EBUSY.The only case that it can't detect is if there is a PHY that may be added to phylink at a later time, and that is what the check above is for.
I've updated the function description to mention this detail:
+/**
+ * phylink_set_max_fixed_link() - set a fixed link configuration for phylink
+ * @pl: a pointer to a &struct phylink returned from phylink_create()
+ *
+ * Set a maximum speed fixed-link configuration for the chosen interface mode
+ * and MAC capabilities for the phylink instance if the instance has not
+ * already been configured with a SFP, fixed link, or in-band AN mode. If the
+ * interface mode is PHY_INTERFACE_MODE_NA, then search the supported
+ * interfaces bitmap for the first interface that gives the fastest supported
+ * speed.
Does this address your concern?
Thanks.
Signature · 2 lines
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/ FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!
Vladimir Oltean
maintainerRe: [PATCH RFC net-next 5/5] net: dsa: always use phylink for CPU and DSA ports
Quoted 11 lines · Russell King (Oracle)
Quoted 10 lines · Russell King (Oracle)
Quoted 5 lines · Vladimir Oltean
Can we please limit
phylink_set_max_link_speed()to just the CPU ports where a fixed-link property is also missing, not just a phy-handle? Although to be entirely correct, we can also haveMLO_AN_INBAND, which wouldn't be covered by these 2 checks and would still represent a valid DT binding.
phylink_set_max_fixed_link()already excludes itself:if (pl->cfg_link_an_mode != MLO_AN_PHY || pl->phydev || pl->sfp_bus)
~~~~~~~~~~
If not NULL, this is an SFP PHY, right? In other words, it's supposed to protect from phylink_sfp_connect_phy() - code involuntarily triggered by phylink_create() -> phylink_register_sfp() - and not from calls to phylink_{,fwnode_}connect_phy() that were initiated by the phylink user between phylink_create() and phylink_set_max_fixed_link(), correct? Those are specified as invalid in the kerneldoc and that's about it - that's not what the checking is for, correct?
But if so, why even check for pl->phydev, if you check for pl->sfp_bus?
Quoted 9 lines
Quoted 9 lines
return -EBUSY;intentionally so that if there is anything specified for the port, be that a fixed link or in-band, then
phylink_set_max_fixed_link()errors out with-EBUSY.The only case that it can't detect is if there is a PHY that may be added to phylink at a later time, and that is what the check above is for.
Here by "PHY added at a later time", you do mean calling phylink_{,fwnode_}connect_phy() after phylink_set_max_fixed_link(), right?
So this is what I don't understand. If we've called phylink_set_max_fixed_link() we've changed pl->cfg_link_an_mode to MLO_AN_FIXED and this will silently break future calls to phylink_{,fwnode_}connect_phy(), so DSA predicts if it's going to call either of those connect_phy() functions, and calls phylink_set_max_fixed_link() only if it won't. Right?
You've structured the checks in this "distributed" way because phylink can't really predict whether phylink_{,fwnode_}connect_phy() will be called after phylink_set_max_fixed_link(), right? I mean, it can probably predict the fwnode_ variant, but not phylink_connect_phy, and this is why it is up to the caller to decide when to call and when not to.
Quoted 13 lines
I've updated the function description to mention this detail:
+/**
+ *phylink_set_max_fixed_link()- set a fixed link configuration for phylink
+ * @pl: a pointer to a &struct phylink returned fromphylink_create()
+ *
+ * Set a maximum speed fixed-link configuration for the chosen interface mode
+ * and MAC capabilities for the phylink instance if the instance has not
+ * already been configured with a SFP, fixed link, or in-band AN mode. If the
+ * interface mode isPHY_INTERFACE_MODE_NA, then search the supported
+ * interfaces bitmap for the first interface that gives the fastest supported
+ * speed.
Quoted 3 lines
Does this address your concern?
Thanks.
Not really, no, sorry, it just confuses me more. It should maybe also say that this function shouldn't be called if phylink_{,fwnode_}connect_phy() is going to be called later.
Can phylink absorb all this logic, and automatically call phylink_set_max_fixed_link() based on the following?
(1) struct phylink_config gets extended with a bool fallback_max_fixed_link.
(2) DSA CPU and DSA ports set this to true in dsa_port_phylink_register().
(3) phylink_set_max_fixed_link() is hooked into this -ENODEV error
condition from phylink_fwnode_phy_connect():
phy_fwnode = fwnode_get_phy_node(fwnode);
if (IS_ERR(phy_fwnode)) {
if (pl->cfg_link_an_mode == MLO_AN_PHY)
return -ENODEV; <- here
return 0;
}Russell King (Oracle)
maintainerRe: [PATCH RFC net-next 5/5] net: dsa: always use phylink for CPU and DSA ports
Quoted 12 lines · Vladimir Oltean
Quoted 11 lines · Russell King (Oracle)
Quoted 10 lines · Russell King (Oracle)
Quoted 5 lines · Vladimir Oltean
Can we please limit
phylink_set_max_link_speed()to just the CPU ports where a fixed-link property is also missing, not just a phy-handle? Although to be entirely correct, we can also haveMLO_AN_INBAND, which wouldn't be covered by these 2 checks and would still represent a valid DT binding.
phylink_set_max_fixed_link()already excludes itself:if (pl->cfg_link_an_mode != MLO_AN_PHY || pl->phydev || pl->sfp_bus)
Quoted 8 lines
~~~~~~~~~~If not NULL, this is an SFP PHY, right? In other words, it's supposed to protect from
phylink_sfp_connect_phy()- code involuntarily triggered byphylink_create()->phylink_register_sfp()- and not from calls to phylink_{,fwnode_}connect_phy() that were initiated by the phylink user betweenphylink_create()andphylink_set_max_fixed_link(), correct? Those are specified as invalid in the kerneldoc and that's about it - that's not what the checking is for, correct?
No, it's not to do with sfps at all, but to do with enforcing the pre-conditions for the function - that entire line is checking that
(a) we are in a sane state to be called, and (b) there is no configuration initialisation beyond the default done by phylink_create() - in other words, there is no in-band or fixed-link specified.
Let's go through this step by step.
1. pl->cfg_link_an_mode != MLO_AN_PHY
The default value for cfg_link_an_mode is MLO_AN_PHY. If it's anything other than that, then a fixed-link or in-band mode has been specified, and we don't want to override that. So this call needs to fail.
2. pl->phydev
If a PHY has been attached, then the pre-condition for calling this function immediately after phylink_create() has been violated, because the only way it can be non-NULL is if someone's called one of the phylink functions that connects a PHY. Note: SFPs will not set their PHY here, because, for them to discover that there's a PHY, the network interface needs to be up, and it will never be up here... but in any case...
3. pl->sfp_bus
If we have a SFP bus, then we definitely are not going to be operating in this default fixed-link mode - because the SFP is going to want to set its own parameters.
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
return -EBUSY;intentionally so that if there is anything specified for the port, be that a fixed link or in-band, then
phylink_set_max_fixed_link()errors out with-EBUSY.
Quoted 6 lines
Quoted 3 lines
Quoted 3 lines
The only case that it can't detect is if there is a PHY that may be added to phylink at a later time, and that is what the check above is for.
Here by "PHY added at a later time", you do mean calling phylink_{,fwnode_}connect_phy() after
phylink_set_max_fixed_link(), right?
Correct.
Quoted 11 lines
So this is what I don't understand. If we've called
phylink_set_max_fixed_link()we've changedpl->cfg_link_an_modetoMLO_AN_FIXEDand this will silently break future calls to phylink_{,fwnode_}connect_phy(), so DSA predicts if it's going to call either of thoseconnect_phy()functions, and callsphylink_set_max_fixed_link()only if it won't. Right?You've structured the checks in this "distributed" way because phylink can't really predict whether phylink_{,fwnode_}connect_phy() will be called after
phylink_set_max_fixed_link(), right? I mean, it can probably predict thefwnode_variant, but notphylink_connect_phy, and this is why it is up to the caller to decide when to call and when not to.
phylink has no idea whether phylink_fwnode_connect_phy() will be called with the same fwnode as phylink_create(), so it really can't make any assumptions about whether there will be a PHY or not.
Quoted 14 lines
Quoted 14 lines
I've updated the function description to mention this detail:
+/**
+ *phylink_set_max_fixed_link()- set a fixed link configuration for phylink
+ * @pl: a pointer to a &struct phylink returned fromphylink_create()
+ *
+ * Set a maximum speed fixed-link configuration for the chosen interface mode
+ * and MAC capabilities for the phylink instance if the instance has not
+ * already been configured with a SFP, fixed link, or in-band AN mode. If the
+ * interface mode isPHY_INTERFACE_MODE_NA, then search the supported
+ * interfaces bitmap for the first interface that gives the fastest supported
+ * speed.
Quoted 5 lines
Quoted 3 lines
Does this address your concern?
Thanks.
Not really, no, sorry, it just confuses me more.
I find that happens a lot when I try to add more documentation to clarify things. I sometimes get to the point of deciding its better _not_ to write any documentation, because documentation just ends up being confusing and people want more and more detail.
I've got to the point in some case where I've had to spell out which keys to press on the keyboard for people to formulate the "[PATCH ...]" thing correctly, because if you put it in quotes, you get people who will include the quotes even if you tell them not to.
I hate documentation, I seem incapable of writing it in a way people can understand.
Quoted 3 lines
It should maybe also
say that this function shouldn't be called if phylink_{,fwnode_}connect_phy() is going to be called later.
It's already a precondition that phylink_{,fwnode_}connect_phy() fail if we're in fixed-link mode (because PHYs have never been supported when in fixed-link mode - if one remembers, the old fixed-link code used to provide its own emulation of a PHY to make fixed-links work.) So PHYs and fixed-links have always been mutually exclusive before phylink, and continue to be so with phylink.
Quoted 6 lines
Can phylink absorb all this logic, and automatically call
phylink_set_max_fixed_link()based on the following?(1) struct
phylink_configgets extended with a boolfallback_max_fixed_link.
(2) DSA CPU and DSA ports set this to true indsa_port_phylink_register().
(3)phylink_set_max_fixed_link()is hooked into this-ENODEVerror
Quoted 8 lines
condition from phylink_fwnode_phy_connect():
phy_fwnode = fwnode_get_phy_node(fwnode);
if (IS_ERR(phy_fwnode)) {
if (pl->cfg_link_an_mode == MLO_AN_PHY)
return -ENODEV; <- here
return 0;
}My question in response would be - why should this DSA specific behaviour be handled completely internally within phylink, when it's a DSA specific behaviour? Why do we need boolean flags for this?
Signature · 2 lines
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/ FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!
Vladimir Oltean
maintainerRe: [PATCH RFC net-next 5/5] net: dsa: always use phylink for CPU and DSA ports
Quoted 29 lines · Russell King (Oracle)
Quoted 12 lines · Vladimir Oltean
Quoted 11 lines · Russell King (Oracle)
Quoted 10 lines · Russell King (Oracle)
Quoted 5 lines · Vladimir Oltean
Can we please limit
phylink_set_max_link_speed()to just the CPU ports where a fixed-link property is also missing, not just a phy-handle? Although to be entirely correct, we can also haveMLO_AN_INBAND, which wouldn't be covered by these 2 checks and would still represent a valid DT binding.
phylink_set_max_fixed_link()already excludes itself:if (pl->cfg_link_an_mode != MLO_AN_PHY || pl->phydev || pl->sfp_bus)Quoted 8 lines
~~~~~~~~~~If not NULL, this is an SFP PHY, right? In other words, it's supposed to protect from
phylink_sfp_connect_phy()- code involuntarily triggered byphylink_create()->phylink_register_sfp()- and not from calls to phylink_{,fwnode_}connect_phy() that were initiated by the phylink user betweenphylink_create()andphylink_set_max_fixed_link(), correct? Those are specified as invalid in the kerneldoc and that's about it - that's not what the checking is for, correct?No, it's not to do with sfps at all, but to do with enforcing the pre-conditions for the function - that entire line is checking that
(a) we are in a sane state to be called, and (b) there is no configuration initialisation beyond the default done byphylink_create()- in other words, there is no in-band or fixed-link specified.
Quoted 7 lines
Let's go through this step by step.
1.
pl->cfg_link_an_mode!=MLO_AN_PHY
The default value forcfg_link_an_modeisMLO_AN_PHY. If it's anything other than that, then a fixed-link or in-band mode has been specified, and we don't want to override that. So this call needs to fail.
Thanks for the explanation.
Yes, I noticed that phylink_set_max_fixed_link() relies on the fact that pl->cfg_link_an_mode has the unset value of 0, which coincidentally is MLO_AN_PHY.
Quoted 8 lines
2.
pl->phydev
If a PHY has been attached, then the pre-condition for calling this function immediately afterphylink_create()has been violated, because the only way it can be non-NULL is if someone's called one of the phylink functions that connects a PHY. Note: SFPs will not set their PHY here, because, for them to discover that there's a PHY, the network interface needs to be up, and it will never be up here... but in any case...
Ok, so this does check for a precondition that the caller did something correctly. But it doesn't (and can't) check that all preconditions and postconditions are satisfied. That's one of my irks, why bother checking the easy to satisfy precondition (which depends on the code organization, static information, easy to check), and give up on the hard one (which depends on the device tree blob, dynamic information, not so easy).
Quoted 12 lines
Quoted 11 lines
So this is what I don't understand. If we've called
phylink_set_max_fixed_link()we've changedpl->cfg_link_an_modetoMLO_AN_FIXEDand this will silently break future calls to phylink_{,fwnode_}connect_phy(), so DSA predicts if it's going to call either of thoseconnect_phy()functions, and callsphylink_set_max_fixed_link()only if it won't. Right?You've structured the checks in this "distributed" way because phylink can't really predict whether phylink_{,fwnode_}connect_phy() will be called after
phylink_set_max_fixed_link(), right? I mean, it can probably predict thefwnode_variant, but notphylink_connect_phy, and this is why it is up to the caller to decide when to call and when not to.
Quoted 3 lines
phylink has no idea whether
phylink_fwnode_connect_phy()will be called with the same fwnode asphylink_create(), so it really can't make any assumptions about whether there will be a PHY or not.
This is interesting. Is there a use case for passing a different fwnode_handle to the 2 functions?
Quoted 10 lines
Quoted 3 lines
It should maybe also
say that this function shouldn't be called if phylink_{,fwnode_}connect_phy() is going to be called later.It's already a precondition that phylink_{,fwnode_}connect_phy() fail if we're in fixed-link mode (because PHYs have never been supported when in fixed-link mode - if one remembers, the old fixed-link code used to provide its own emulation of a PHY to make fixed-links work.) So PHYs and fixed-links have always been mutually exclusive before phylink, and continue to be so with phylink.
Define "fail" exactly, because if I look in phylink_fwnode_phy_connect(), I see:
/* Fixed links and 802.3z are handled without needing a PHY */ if (pl->cfg_link_an_mode == MLO_AN_FIXED || (pl->cfg_link_an_mode == MLO_AN_INBAND && phy_interface_mode_is_8023z(pl->link_interface))) return 0; <- does this count as failure?
This is why dsa_port_phylink_register() calls phylink_of_phy_connect() without checking whether it has a fixed-link or a PHY, because it doesn't fail even if it doesn't do anything.
In fact I've wanted to make a correction to my previous phrasing that "this function shouldn't be called if phylink_{,fwnode_}connect_phy() is going to be called later". The correction is "... with a phy-handle".
Quoted 15 lines
Quoted 6 lines
Can phylink absorb all this logic, and automatically call
phylink_set_max_fixed_link()based on the following?(1) struct
phylink_configgets extended with a boolfallback_max_fixed_link.
(2) DSA CPU and DSA ports set this to true indsa_port_phylink_register().
(3)phylink_set_max_fixed_link()is hooked into this-ENODEVerrorQuoted 8 lines
condition from phylink_fwnode_phy_connect(): phy_fwnode = fwnode_get_phy_node(fwnode); if (IS_ERR(phy_fwnode)) { if (pl->cfg_link_an_mode == MLO_AN_PHY) return -ENODEV; <- here return 0; }
Quoted 3 lines
My question in response would be - why should this DSA specific behaviour be handled completely internally within phylink, when it's a DSA specific behaviour? Why do we need boolean flags for this?
Because the end result will be simpler if we respect the separation of concerns that continues to exist, and it's still phylink's business to say what is and isn't valid. DSA still isn't aware of the bindings required by phylink, it just passes its fwnode to it. Practically speaking, I wouldn't be scratching my head as to why we're checking for half the prerequisites of phylink_set_max_fixed_link() in one place and for the other half in another.
True, through this patch set DSA is creating its own context specific extension of phylink bindings, but arguably those existed before DSA was even integrated with phylink, and we're just fixing something now we didn't realize at the time we'd need to do.
I can reverse the question, why would phylink even want to be involved in how the max fixed link parameters are deduced, and it doesn't just require that a fixed-link software node is constructed somehow (irrelevant to phylink how), and phylink is just modified to find and work with that if it exists? Isn't it for the exact same reason, separation of concerns, that it's easiest for phylink to figure out what is the most appropriate maximum fixed-link configuration?
Russell King (Oracle)
maintainerRe: [PATCH RFC net-next 5/5] net: dsa: always use phylink for CPU and DSA ports
Quoted 24 lines · Vladimir Oltean
Quoted 7 lines · Russell King (Oracle)
Let's go through this step by step.
1.
pl->cfg_link_an_mode!=MLO_AN_PHY
The default value forcfg_link_an_modeisMLO_AN_PHY. If it's anything other than that, then a fixed-link or in-band mode has been specified, and we don't want to override that. So this call needs to fail.Thanks for the explanation.
Yes, I noticed that
phylink_set_max_fixed_link()relies on the fact thatpl->cfg_link_an_modehas the unset value of 0, which coincidentally isMLO_AN_PHY.Quoted 8 lines
2.
pl->phydev
If a PHY has been attached, then the pre-condition for calling this function immediately afterphylink_create()has been violated, because the only way it can be non-NULL is if someone's called one of the phylink functions that connects a PHY. Note: SFPs will not set their PHY here, because, for them to discover that there's a PHY, the network interface needs to be up, and it will never be up here... but in any case...
Quoted 6 lines
Ok, so this does check for a precondition that the caller did something correctly. But it doesn't (and can't) check that all preconditions and postconditions are satisfied. That's one of my irks, why bother checking the easy to satisfy precondition (which depends on the code organization, static information, easy to check), and give up on the hard one (which depends on the device tree blob, dynamic information, not so easy).
So what you're asking is: why bother doing any checks if you can't do all of them?
My response would be: isn't best effort better than doing nothing?
In my mind, it is best effort, because:
a) if you've called it when the preconditions (with the exception of a future PHY) are not satisfied, then it fails with -EBUSY.
b) if this call succeeds, then it locks out the future ability to bind a PHY.
So, if one forgets to check whether there'll be a future PHY, and call this anyway, then a future attempt to bind a PHY to phylink fails and you get a failure.
Considering that we are only talking about DSA making use of this (no other network driver has this behaviour) and this is being handled by core DSA code, we could label this up as "this is for DSA use only."
Quoted 12 lines
Quoted 12 lines
Quoted 11 lines
So this is what I don't understand. If we've called
phylink_set_max_fixed_link()we've changedpl->cfg_link_an_modetoMLO_AN_FIXEDand this will silently break future calls to phylink_{,fwnode_}connect_phy(), so DSA predicts if it's going to call either of thoseconnect_phy()functions, and callsphylink_set_max_fixed_link()only if it won't. Right?You've structured the checks in this "distributed" way because phylink can't really predict whether phylink_{,fwnode_}connect_phy() will be called after
phylink_set_max_fixed_link(), right? I mean, it can probably predict thefwnode_variant, but notphylink_connect_phy, and this is why it is up to the caller to decide when to call and when not to.
Quoted 6 lines
Quoted 3 lines
phylink has no idea whether
phylink_fwnode_connect_phy()will be called with the same fwnode asphylink_create(), so it really can't make any assumptions about whether there will be a PHY or not.This is interesting. Is there a use case for passing a different
fwnode_handleto the 2 functions?
That depends on the driver. It looks like drivers/net/ethernet/ti/am65-cpsw-nuss.c may well pass in different nodes in the firmware tree.
Quoted 11 lines
Quoted 10 lines
Quoted 3 lines
It should maybe also
say that this function shouldn't be called if phylink_{,fwnode_}connect_phy() is going to be called later.It's already a precondition that phylink_{,fwnode_}connect_phy() fail if we're in fixed-link mode (because PHYs have never been supported when in fixed-link mode - if one remembers, the old fixed-link code used to provide its own emulation of a PHY to make fixed-links work.) So PHYs and fixed-links have always been mutually exclusive before phylink, and continue to be so with phylink.
Quoted 7 lines
Define "fail" exactly, because if I look in
phylink_fwnode_phy_connect(), I see:/* Fixed links and 802.3z are handled without needing a PHY */ if (pl->cfg_link_an_mode == MLO_AN_FIXED || (pl->cfg_link_an_mode == MLO_AN_INBAND && phy_interface_mode_is_8023z(pl->link_interface))) return 0; <- does this count as failure?
Sorry, yes, that is correct - it ignores the attempt (so drivers don't have to conditionalise the call for this everywhere.)
Quoted 7 lines
This is why
dsa_port_phylink_register()callsphylink_of_phy_connect()without checking whether it has a fixed-link or a PHY, because it doesn't fail even if it doesn't do anything.In fact I've wanted to make a correction to my previous phrasing that "this function shouldn't be called if phylink_{,fwnode_}connect_phy() is going to be called later". The correction is "... with a phy-handle".
I'm not sure that clarification makes sense when talking about phylink_connect_phy(), so I think if you're clarifying it with a firmware property, you're only talking about phylink_fwnode_connect_phy() now?
Quoted 32 lines
Quoted 15 lines
Quoted 6 lines
Can phylink absorb all this logic, and automatically call
phylink_set_max_fixed_link()based on the following?(1) struct
phylink_configgets extended with a boolfallback_max_fixed_link.
(2) DSA CPU and DSA ports set this to true indsa_port_phylink_register().
(3)phylink_set_max_fixed_link()is hooked into this-ENODEVerrorQuoted 8 lines
condition from phylink_fwnode_phy_connect(): phy_fwnode = fwnode_get_phy_node(fwnode); if (IS_ERR(phy_fwnode)) { if (pl->cfg_link_an_mode == MLO_AN_PHY) return -ENODEV; <- here return 0; }Quoted 3 lines
My question in response would be - why should this DSA specific behaviour be handled completely internally within phylink, when it's a DSA specific behaviour? Why do we need boolean flags for this?
Because the end result will be simpler if we respect the separation of concerns that continues to exist, and it's still phylink's business to say what is and isn't valid. DSA still isn't aware of the bindings required by phylink, it just passes its fwnode to it. Practically speaking, I wouldn't be scratching my head as to why we're checking for half the prerequisites of
phylink_set_max_fixed_link()in one place and for the other half in another.True, through this patch set DSA is creating its own context specific extension of phylink bindings, but arguably those existed before DSA was even integrated with phylink, and we're just fixing something now we didn't realize at the time we'd need to do.
Quoted 7 lines
I can reverse the question, why would phylink even want to be involved in how the max fixed link parameters are deduced, and it doesn't just require that a fixed-link software node is constructed somehow (irrelevant to phylink how), and phylink is just modified to find and work with that if it exists? Isn't it for the exact same reason, separation of concerns, that it's easiest for phylink to figure out what is the most appropriate maximum fixed-link configuration?
If that could be done, I'd love it, because then we don't have this in phylink at all, and it can all be a DSA problem to solve. It also means that others won't be tempted to use the interface incorrectly.
I'm not sure how practical that is when we have both DT and ACPI to deal with, and ACPI is certainly out of my knowledge area to be able to construct a software node to specify a fixed-link. Maybe it can be done at the fwnode layer? I don't know.
Do you have a handy example of what you're suggesting?
Signature · 2 lines
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/ FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!
Vladimir Oltean
maintainerRe: [PATCH RFC net-next 5/5] net: dsa: always use phylink for CPU and DSA ports
Quoted 4 lines · Russell King (Oracle)
Quoted 4 lines
This is why
dsa_port_phylink_register()callsphylink_of_phy_connect()without checking whether it has a fixed-link or a PHY, because it doesn't fail even if it doesn't do anything.
Quoted 8 lines
Quoted 3 lines
In fact I've wanted to make a correction to my previous phrasing that "this function shouldn't be called if phylink_{,fwnode_}connect_phy() is going to be called later". The correction is "... with a phy-handle".
I'm not sure that clarification makes sense when talking about
phylink_connect_phy(), so I think if you're clarifying it with a firmware property, you're only talking aboutphylink_fwnode_connect_phy()now?
Yes, it's super hard to verbalize, and this is the reason why I didn't add "... with a phy-handle" in the first place.
I wanted to say: phylink_connect_phy(), OR phylink_fwnode_connect_phy() WITH a phy-handle. I shouldn't have conflated them in the first place.
Quoted 40 lines
Quoted 32 lines
Quoted 15 lines
Quoted 6 lines
Can phylink absorb all this logic, and automatically call
phylink_set_max_fixed_link()based on the following?(1) struct
phylink_configgets extended with a boolfallback_max_fixed_link.
(2) DSA CPU and DSA ports set this to true indsa_port_phylink_register().
(3)phylink_set_max_fixed_link()is hooked into this-ENODEVerrorQuoted 8 lines
condition from phylink_fwnode_phy_connect(): phy_fwnode = fwnode_get_phy_node(fwnode); if (IS_ERR(phy_fwnode)) { if (pl->cfg_link_an_mode == MLO_AN_PHY) return -ENODEV; <- here return 0; }Quoted 3 lines
My question in response would be - why should this DSA specific behaviour be handled completely internally within phylink, when it's a DSA specific behaviour? Why do we need boolean flags for this?
Because the end result will be simpler if we respect the separation of concerns that continues to exist, and it's still phylink's business to say what is and isn't valid. DSA still isn't aware of the bindings required by phylink, it just passes its fwnode to it. Practically speaking, I wouldn't be scratching my head as to why we're checking for half the prerequisites of
phylink_set_max_fixed_link()in one place and for the other half in another.True, through this patch set DSA is creating its own context specific extension of phylink bindings, but arguably those existed before DSA was even integrated with phylink, and we're just fixing something now we didn't realize at the time we'd need to do.
Quoted 7 lines
I can reverse the question, why would phylink even want to be involved in how the max fixed link parameters are deduced, and it doesn't just require that a fixed-link software node is constructed somehow (irrelevant to phylink how), and phylink is just modified to find and work with that if it exists? Isn't it for the exact same reason, separation of concerns, that it's easiest for phylink to figure out what is the most appropriate maximum fixed-link configuration?
Quoted 8 lines
If that could be done, I'd love it, because then we don't have this in phylink at all, and it can all be a DSA problem to solve. It also means that others won't be tempted to use the interface incorrectly.
I'm not sure how practical that is when we have both DT and ACPI to deal with, and ACPI is certainly out of my knowledge area to be able to construct a software node to specify a fixed-link. Maybe it can be done at the fwnode layer? I don't know.
I don't want to be misunderstood. I brought up software nodes because I'm sure you must have thought about this too, before proposing what you did here. And unless there's a technical reason against software nodes (which there doesn't appear to be, but I don't want to get ahead of myself), I figured you must be OK with phylink absorbing the logic, case in which I just don't understand why you are pushing back on a proposal how to make phylink absorb the logic completely.
Quoted 1 line
Do you have a handy example of what you're suggesting?
No, I didn't, but I thought, how hard can it be, and here's a hacked up attempt on one of my boards:
From 5d002f03c91b357be304d41f7422969d0dd89f5b Mon Sep 17 00:00:00 2001
From: Vladimir Oltean <[email protected]>
Date: Thu, 7 Jul 2022 21:04:32 +0300
Subject: [PATCH] dsa_port_fixup_broken_dt
--- arch/arm/boot/dts/ls1021a-tsn.dts | 5 -- drivers/base/swnode.c | 14 +++- drivers/net/dsa/sja1105/sja1105_main.c | 4 +- include/linux/property.h | 4 ++ net/dsa/dsa_priv.h | 2 +- net/dsa/port.c | 99 +++++++++++++++++++++----- net/dsa/slave.c | 2 +- 7 files changed, 100 insertions(+), 30 deletions(-)
arch/arm/boot/dts/ls1021a-tsn.dts +0 -5
@@ -94,11 +94,6 @@ port@4 { rx-internal-delay-ps = <0>; tx-internal-delay-ps = <0>; reg = <4>; - - fixed-link { - speed = <1000>; - full-duplex; - }; }; }; };
drivers/base/swnode.c +12 -2
@@ -972,8 +972,9 @@ void software_node_unregister(const struct software_node *node)EXPORT_SYMBOL_GPL (software_node_unregister);struct fwnode_handle * -fwnode_create_software_node (const struct property_entry *properties, -const struct fwnode_handle *parent) +fwnode_create_named_software_node (const struct property_entry *properties, +const struct fwnode_handle *parent, +const char *name) {struct fwnode_handle *fwnode;struct software_node *node;
@@ -991,6 +992,7 @@ fwnode_create_software_node(const struct property_entry *properties,return ERR_CAST (node); node->parent = p ? p->node :NULL ; + node->name = name; fwnode =swnode_register (node, p,1 );if (IS_ERR (fwnode))
@@ -998,6 +1000,14 @@ fwnode_create_software_node(const struct property_entry *properties,return fwnode; } +EXPORT_SYMBOL_GPL (fwnode_create_named_software_node); + +struct fwnode_handle * +fwnode_create_software_node (const struct property_entry *properties, +const struct fwnode_handle *parent) +{ +return fwnode_create_named_software_node (properties, parent,NULL ); +}EXPORT_SYMBOL_GPL (fwnode_create_software_node);void fwnode_remove_software_node (struct fwnode_handle *fwnode)
drivers/net/dsa/sja1105/sja1105_main.c +2 -2
@@ -1218,8 +1218,8 @@ static int sja1105_parse_ports_node(struct sja1105_private *priv,if (!of_phy_is_fixed_link (child)) {dev_err (dev,"phy-handle or fixed-link " "properties missing!\n" ); -of_node_put (child); -return -ENODEV ; +// of_node_put(child); +// return -ENODEV; }/* phy-handle is missing, but fixed-link isn't. * So it's a fixed link. Default to PHY role.
include/linux/property.h +4 -0
@@ -492,6 +492,10 @@ void software_node_unregister(const struct software_node *node);struct fwnode_handle *fwnode_create_software_node (const struct property_entry *properties,const struct fwnode_handle *parent); +struct fwnode_handle * +fwnode_create_named_software_node (const struct property_entry *properties, +const struct fwnode_handle *parent, +const char *name);void fwnode_remove_software_node (struct fwnode_handle *fwnode);int device_add_software_node (struct device *dev,const struct software_node *node);
net/dsa/dsa_priv.h +1 -1
@@ -284,7 +284,7 @@ int dsa_port_mrp_add_ring_role(const struct dsa_port *dp, const struct switchdev_obj_ring_role_mrp *mrp);int dsa_port_mrp_del_ring_role (const struct dsa_port *dp,const struct switchdev_obj_ring_role_mrp *mrp); -int dsa_port_phylink_create (struct dsa_port *dp); +int dsa_port_phylink_create (struct dsa_port *dp,struct fwnode_handle *fwnode);int dsa_port_link_register_of (struct dsa_port *dp);void dsa_port_link_unregister_of (struct dsa_port *dp);int dsa_port_hsr_join (struct dsa_port *dp,struct net_device *hsr);
net/dsa/port.c +80 -19
142 lines not on this page · raw message
net/dsa/slave.c +1 -1
@@ -2245,7 +2245,7 @@ static int dsa_slave_phy_setup(struct net_device *slave_dev) dp->pl_config.poll_fixed_state = true; } - ret =dsa_port_phylink_create (dp); + ret =dsa_port_phylink_create (dp,of_fwnode_handle (dp->dn));if (ret)return ret;
Signature · 32 lines
2.25.1
It boots and works:
[ 4.315754] sja1105 spi0.1: configuring for fixed/rgmii link mode
[ 4.322653] sja1105 spi0.1 swp5 (uninitialized): PHY [mdio@2d24000:06] driver [Broadcom BCM5464] (irq=POLL)
[ 4.334796] sja1105 spi0.1 swp2 (uninitialized): PHY [mdio@2d24000:03] driver [Broadcom BCM5464] (irq=POLL)
[ 4.345853] sja1105 spi0.1 swp3 (uninitialized): PHY [mdio@2d24000:04] driver [Broadcom BCM5464] (irq=POLL)
[ 4.356859] sja1105 spi0.1 swp4 (uninitialized): PHY [mdio@2d24000:05] driver [Broadcom BCM5464] (irq=POLL)
[ 4.367245] device eth2 entered promiscuous mode
[ 4.371864] DSA: tree 0 setup
[ 4.376971] sja1105 spi0.1: Link is Up - 1Gbps/Full - flow control off
(...)
root@black:~# ip link set swp2 up && dhclient -i swp2 && ip addr show swp2
[ 64.762756] fsl-gianfar soc:ethernet@2d90000 eth2: Link is Up - 1Gbps/Full - flow control off
[ 64.771530] sja1105 spi0.1 swp2: configuring for phy/rgmii-id link mode
[ 68.955048] sja1105 spi0.1 swp2: Link is Up - 1Gbps/Full - flow control off
12: swp2@eth2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 00:1f:7b:63:02:48 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.68/24 brd 10.0.0.255 scope global dynamic swp2
valid_lft 600sec preferred_lft 600sec
It's by far the messiest patch I've posted to the list (in the interest
of responding quickly), but if you study the code you can obviously see
what's missing, basically I've hardcoded the speed to 1000 and I'm
copying the phy-mode from the real DT node.
Unfortunately I don't have the time (and most importantly the interest)
in pushing this any further than that. If you want to take this from
here and integrate it with phylink_get_caps() I'd be glad to review
the result. Otherwise, feel free to continue with phylink_set_max_fixed_link().Russell King (Oracle)
maintainerRe: [PATCH RFC net-next 5/5] net: dsa: always use phylink for CPU and DSA ports
Quoted 14 lines · Vladimir Oltean
Quoted 4 lines · Russell King (Oracle)
Quoted 4 lines
This is why
dsa_port_phylink_register()callsphylink_of_phy_connect()without checking whether it has a fixed-link or a PHY, because it doesn't fail even if it doesn't do anything.Quoted 8 lines
Quoted 3 lines
In fact I've wanted to make a correction to my previous phrasing that "this function shouldn't be called if phylink_{,fwnode_}connect_phy() is going to be called later". The correction is "... with a phy-handle".
I'm not sure that clarification makes sense when talking about
phylink_connect_phy(), so I think if you're clarifying it with a firmware property, you're only talking aboutphylink_fwnode_connect_phy()now?
Quoted 5 lines
Yes, it's super hard to verbalize, and this is the reason why I didn't add "... with a phy-handle" in the first place.
I wanted to say:
phylink_connect_phy(), ORphylink_fwnode_connect_phy()WITH a phy-handle. I shouldn't have conflated them in the first place.
Ah, right, because I interpreted it quite differently!
Quoted 49 lines
Quoted 40 lines
Quoted 32 lines
Quoted 15 lines
Quoted 6 lines
Can phylink absorb all this logic, and automatically call
phylink_set_max_fixed_link()based on the following?(1) struct
phylink_configgets extended with a boolfallback_max_fixed_link.
(2) DSA CPU and DSA ports set this to true indsa_port_phylink_register().
(3)phylink_set_max_fixed_link()is hooked into this-ENODEVerrorQuoted 8 lines
condition from phylink_fwnode_phy_connect(): phy_fwnode = fwnode_get_phy_node(fwnode); if (IS_ERR(phy_fwnode)) { if (pl->cfg_link_an_mode == MLO_AN_PHY) return -ENODEV; <- here return 0; }Quoted 3 lines
My question in response would be - why should this DSA specific behaviour be handled completely internally within phylink, when it's a DSA specific behaviour? Why do we need boolean flags for this?
Because the end result will be simpler if we respect the separation of concerns that continues to exist, and it's still phylink's business to say what is and isn't valid. DSA still isn't aware of the bindings required by phylink, it just passes its fwnode to it. Practically speaking, I wouldn't be scratching my head as to why we're checking for half the prerequisites of
phylink_set_max_fixed_link()in one place and for the other half in another.True, through this patch set DSA is creating its own context specific extension of phylink bindings, but arguably those existed before DSA was even integrated with phylink, and we're just fixing something now we didn't realize at the time we'd need to do.
Quoted 7 lines
I can reverse the question, why would phylink even want to be involved in how the max fixed link parameters are deduced, and it doesn't just require that a fixed-link software node is constructed somehow (irrelevant to phylink how), and phylink is just modified to find and work with that if it exists? Isn't it for the exact same reason, separation of concerns, that it's easiest for phylink to figure out what is the most appropriate maximum fixed-link configuration?
Quoted 8 lines
If that could be done, I'd love it, because then we don't have this in phylink at all, and it can all be a DSA problem to solve. It also means that others won't be tempted to use the interface incorrectly.
I'm not sure how practical that is when we have both DT and ACPI to deal with, and ACPI is certainly out of my knowledge area to be able to construct a software node to specify a fixed-link. Maybe it can be done at the fwnode layer? I don't know.
Quoted 7 lines
I don't want to be misunderstood. I brought up software nodes because I'm sure you must have thought about this too, before proposing what you did here. And unless there's a technical reason against software nodes (which there doesn't appear to be, but I don't want to get ahead of myself), I figured you must be OK with phylink absorbing the logic, case in which I just don't understand why you are pushing back on a proposal how to make phylink absorb the logic completely.
The reason I hadn't is because switching DSA to fwnode brings with it issues for ACPI, and Andrew wants to be very careful about ACPI in networking - and I think quite rightly. As soon as one switches from DT APIs to fwnode APIs, you basically permit people an easy path to re-use DT properties in ACPI-land without the ACPI issues being first considered.
So, I think if we did go this route, we need Andrew's input.
Quoted 4 lines
Quoted 1 line
Do you have a handy example of what you're suggesting?
No, I didn't, but I thought, how hard can it be, and here's a hacked up attempt on one of my boards:
Thanks - that looks like something that should be possible to do, and way better than trying to shoe-horn this into phylink.
My only comment would be that Andrew would disagree with you about this being "fixing up broken DT" - he has actively encouraged some drivers to adopt this "default" mode, which means it's anything but "broken" but it really is part of the DSA firmware description.
Quoted 18 lines
[ 4.315754] sja1105 spi0.1: configuring for fixed/rgmii link mode
[ 4.322653] sja1105 spi0.1 swp5 (uninitialized): PHY [mdio@2d24000:06] driver [Broadcom BCM5464] (irq=POLL)
[ 4.334796] sja1105 spi0.1 swp2 (uninitialized): PHY [mdio@2d24000:03] driver [Broadcom BCM5464] (irq=POLL)
[ 4.345853] sja1105 spi0.1 swp3 (uninitialized): PHY [mdio@2d24000:04] driver [Broadcom BCM5464] (irq=POLL)
[ 4.356859] sja1105 spi0.1 swp4 (uninitialized): PHY [mdio@2d24000:05] driver [Broadcom BCM5464] (irq=POLL)
[ 4.367245] device eth2 entered promiscuous mode
[ 4.371864] DSA: tree 0 setup
[ 4.376971] sja1105 spi0.1: Link is Up - 1Gbps/Full - flow control off
(...)
root@black:~# ip link set swp2 up && dhclient -i swp2 && ip addr show swp2
[ 64.762756] fsl-gianfar soc:ethernet@2d90000 eth2: Link is Up - 1Gbps/Full - flow control off
[ 64.771530] sja1105 spi0.1 swp2: configuring for phy/rgmii-id link mode
[ 68.955048] sja1105 spi0.1 swp2: Link is Up - 1Gbps/Full - flow control off
12: swp2@eth2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 00:1f:7b:63:02:48 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.68/24 brd 10.0.0.255 scope global dynamic swp2
valid_lft 600sec preferred_lft 600secQuoted 4 lines
It's by far the messiest patch I've posted to the list (in the interest of responding quickly), but if you study the code you can obviously see what's missing, basically I've hardcoded the speed to 1000 and I'm copying the phy-mode from the real DT node.
Yep - there's at least one other property we need to carry over from the DT node, which is the "ethernet" property.
Quoted 4 lines
Unfortunately I don't have the time (and most importantly the interest) in pushing this any further than that. If you want to take this from here and integrate it with
phylink_get_caps()I'd be glad to review the result. Otherwise, feel free to continue withphylink_set_max_fixed_link().
I think this could be a much better solution to this problem, quite simply because we then don't end up with phylink_set_max_fixed_link() which could be abused - and this keeps the complexity where it should be, in the DSA code.
As I say, though, I think we need Andrew's input on this. Andrew?
I'll look at turning this into a proper solution tomorrow if Andrew is okay with the fwnode change.
Signature · 2 lines
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/ FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!
Vladimir Oltean
maintainerRe: [PATCH RFC net-next 5/5] net: dsa: always use phylink for CPU and DSA ports
Quoted 13 lines · Russell King (Oracle)
Quoted 5 lines
Quoted 4 lines
I'm not sure how practical that is when we have both DT and ACPI to deal with, and ACPI is certainly out of my knowledge area to be able to construct a software node to specify a fixed-link. Maybe it can be done at the fwnode layer? I don't know.
Quoted 7 lines
I don't want to be misunderstood. I brought up software nodes because I'm sure you must have thought about this too, before proposing what you did here. And unless there's a technical reason against software nodes (which there doesn't appear to be, but I don't want to get ahead of myself), I figured you must be OK with phylink absorbing the logic, case in which I just don't understand why you are pushing back on a proposal how to make phylink absorb the logic completely.
Quoted 8 lines
The reason I hadn't is because switching DSA to fwnode brings with it issues for ACPI, and Andrew wants to be very careful about ACPI in networking - and I think quite rightly. As soon as one switches from DT APIs to fwnode APIs, you basically permit people an easy path to re-use DT properties in ACPI-land without the ACPI issues being first considered.
Yep - there's at least one other property we need to carry over from the DT node, which is the "ethernet" property.
I've cropped only these segments because there is something I apparently need to highlight. What my patch does is _not_ at the device fwnode level (in fact, DSA ports do not have a struct device, only the switch does), but indeed at the most crude fwnode_handle level. And the fwnode_handles I'm creating using the software_node API are not connected in any way with the device. I'm not replacing the device's fwnodes with prosthetic ones. The fact that I wrote "dn->fwnode.secondary = new_port_fwnode;" is just a cheap hack to minimize the patch delta so I wouldn't have to transport the software fwnode_handle from one place to another within dsa_port_link_register_of(). This should definitely dissapear in the final solution. In fact, as long as phylink doesn't keep a reference on the fwnode after phylink_create() or phylink_fwnode_phy_connect(), I'm pretty sure that the software node can even be deallocated during the probing stage, no need to keep it for the entire lifetime of the device.
Therefore, no, we don't need the "ethernet" phandle in the software node we create, because we just use that to pass it to phylink. We still keep our original OF node for the rest of the activities. We don't even need the "reg" u32 property, I just added that for no reason (I wasn't completely sure what the API offers, then I didn't remove it).
So the concern that this software node can be abused for a transition to ACPI is quite overestimated. Nothing in DSA is "switched to fwnode" per se, and the creation of a fwnode is just part of "speaking the software node language", which phylink already happily understands and so, needs no change. Just my 2 cents.
Russell King (Oracle)
maintainerRe: [PATCH RFC net-next 5/5] net: dsa: always use phylink for CPU and DSA ports
In reply to Vladimir OlteanHi,
Quoted 1 line · Vladimir Oltean
+static int
dsa_port_fixup_broken_dt(struct dsa_port *dp)
As I mentioned, I doubt that Andrew considers this "broken DT" as he's been promoting this as a standard DSA feature.
Quoted 11 lines
net/dsa/port.c +11
-0+{ +struct property_entry fixed_link_props[] = { +PROPERTY_ENTRY_BOOL ("full-duplex" ), +PROPERTY_ENTRY_U32 ("speed" ,1000 ),/* TODO determine actual speed */ + {}, + }; +struct property_entry port_props[3 ] = {}; +struct fwnode_handle *fixed_link_fwnode; +struct fwnode_handle *new_port_fwnode; +struct device_node *dn = dp->dn; +phy_interface_t mode;
net/dsa/port.c static int dsa_port_phylink_register(struct dsa_port *dp) · line 1675
Quoted 10 lines
net/dsa/port.c +10
-0+int err; + +if (of_parse_phandle (dn,"phy-handle" ,0 ) || +of_phy_is_fixed_link (dn)) +/* Nothing broken, nothing to fix. +* TODO: As discussed with Russell, maybe phylink could provide +* a more comprehensive helper to determine what constitutes a +* valid fwnode binding than this guerilla kludge. +*/ +return 0 ;
I think this is sufficient. Yes, phylink accepts "phy" and "phy-device" because it has to for compatibility with other drivers, but the binding document for DSA quite clearly states that "phy-handle" is what DSA accepts, so DT in the kernel will be validated against the yaml file and enforce correctness here.
We do need to check for "sfp" being present as well.
net/dsa/port.c static int dsa_port_phylink_register(struct dsa_port *dp) · line 1682
Quoted 7 lines
net/dsa/port.c +7
-0+ + err =of_get_phy_mode (dn, &mode); +if (err) +/* TODO this may be missing too, ask the driver for the +* max-speed interface mode for this port +*/ + mode =PHY_INTERFACE_MODE_NA ;
I think it would be easier to omit the phy-mode property in the swnode if it isn't present in DT, because then we can handle that in dsa_port_phylink_create() as I've done in my patch series via the ds->ops->phylink_get_caps() method.
Review
Quoted 2 lines
(quoted diff) +2
-0+ + port_props[0] = PROPERTY_ENTRY_U32("reg", dp->index);
You said in one of your other replies that this node we're constructing is only for phylink, do we need the "reg" property? phylink doesn't care about it.
Signature · 2 lines
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/ FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!
Re: [PATCH RFC net-next 5/5] net: dsa: always use phylink for CPU and DSA ports
Quoted 51 lines · On Fri, 8 Jul 2022 16:25:03 +0100 "Russell King (Oracle)"…
Hi,
Quoted 1 line · Vladimir Oltean
+static int
dsa_port_fixup_broken_dt(struct dsa_port *dp)As I mentioned, I doubt that Andrew considers this "broken DT" as he's been promoting this as a standard DSA feature.
Quoted 11 lines
net/dsa/port.c +11
-0+{ +struct property_entry fixed_link_props[] = { +PROPERTY_ENTRY_BOOL ("full-duplex" ), +PROPERTY_ENTRY_U32 ("speed" ,1000 ),/* TODO determine actual speed */ + {}, + }; +struct property_entry port_props[3 ] = {}; +struct fwnode_handle *fixed_link_fwnode; +struct fwnode_handle *new_port_fwnode; +struct device_node *dn = dp->dn; +phy_interface_t mode;net/dsa/port.c static int dsa_port_phylink_register(struct dsa_port *dp) · line 1675
Quoted 10 lines
net/dsa/port.c +10
-0+int err; + +if (of_parse_phandle (dn,"phy-handle" ,0 ) || +of_phy_is_fixed_link (dn)) +/* Nothing broken, nothing to fix. +* TODO: As discussed with Russell, maybe phylink could provide +* a more comprehensive helper to determine what constitutes a +* valid fwnode binding than this guerilla kludge. +*/ +return 0 ;I think this is sufficient. Yes, phylink accepts "phy" and "phy-device" because it has to for compatibility with other drivers, but the binding document for DSA quite clearly states that "phy-handle" is what DSA accepts, so DT in the kernel will be validated against the yaml file and enforce correctness here.
We do need to check for "sfp" being present as well.
net/dsa/port.c static int dsa_port_phylink_register(struct dsa_port *dp) · line 1682
Quoted 7 lines
net/dsa/port.c +7
-0+ + err =of_get_phy_mode (dn, &mode); +if (err) +/* TODO this may be missing too, ask the driver for the +* max-speed interface mode for this port +*/ + mode =PHY_INTERFACE_MODE_NA ;I think it would be easier to omit the phy-mode property in the swnode if it isn't present in DT, because then we can handle that in
dsa_port_phylink_create()as I've done in my patch series via theds->ops->phylink_get_caps()method.
Quoted 6 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+ + port_props[0] = PROPERTY_ENTRY_U32("reg", dp->index);You said in one of your other replies that this node we're constructing is only for phylink, do we need the "reg" property? phylink doesn't care about it.
We don't. Vladimir wrote: "We don't even need the "reg" u32 property, I just added that for no reason (I wasn't completely sure what the API offers, then I didn't remove it)."
Marek
Russell King (Oracle)
maintainerRe: [PATCH RFC net-next 5/5] net: dsa: always use phylink for CPU and DSA ports
In reply to Vladimir OlteanQuoted 19 lines · Vladimir Oltean
Hello,
Quoted 16 lines · Russell King (Oracle)
net/dsa/port.c +1
-0@@ -1525,6 +1525,7 @@ int dsa_port_phylink_create(struct dsa_port *dp) {struct dsa_switch *ds = dp->ds;phy_interface_t mode, def_mode; +struct device_node *phy_np;int err;/* Presence of phylink_mac_link_state or phylink_mac_an_restart is @@ -1559,6 +1560,13 @@ int dsa_port_phylink_create(struct dsa_port *dp)return PTR_ERR (dp->pl); }
Quoted 11 lines
net/dsa/port.c int dsa_port_phylink_create(struct dsa_port *dp) · line 1567
Quoted 5 lines
net/dsa/port.c +5
-0+if (dp->type ==DSA_PORT_TYPE_CPU || dp->type ==DSA_PORT_TYPE_DSA ) { + phy_np =of_parse_phandle (dp->dn,"phy-handle" ,0 ); +of_node_put (phy_np); +if (!phy_np) + err =phylink_set_max_fixed_link (dp->pl);Can we please limit
phylink_set_max_link_speed()to just the CPU ports where a fixed-link property is also missing, not just a phy-handle? Although to be entirely correct, we can also haveMLO_AN_INBAND, which wouldn't be covered by these 2 checks and would still represent a valid DT binding.
More importantly, we need your input on Ocelot, which you are listed as a maintainer for, and Ocelot is the only DSA driver that does stuff differently (due to the rate adapting PCS). It doesn't set mac_capabilities, and therefore phylink_set_max_fixed_link() will not work here.
Has Ocelot ever made use of this DSA feature where, when nothing is specified for a CPU or DSA port, we use an effective fixed-link setup with an interface mode that gives the highest speed? Or does this not apply to this DSA driver?
Thanks.
Signature · 2 lines
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/ FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!
Vladimir Oltean
maintainerRe: [PATCH RFC net-next 5/5] net: dsa: always use phylink for CPU and DSA ports
Quoted 6 lines · Russell King (Oracle)
More importantly, we need your input on Ocelot, which you are listed as a maintainer for, and Ocelot is the only DSA driver that does stuff differently (due to the rate adapting PCS). It doesn't set
mac_capabilities, and thereforephylink_set_max_fixed_link()will not work here.
Quoted 6 lines
Has Ocelot ever made use of this DSA feature where, when nothing is specified for a CPU or DSA port, we use an effective fixed-link setup with an interface mode that gives the highest speed? Or does this not apply to this DSA driver?
Thanks.
I'm fine with both the ocelot and sja1105 drivers.
The ocelot driver has 3 users:
- felix_vsc9959 (arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi) on NXP LS1028A, where the CPU ports have and have always had a fixed-link node in the SoC dtsi. LS1028A based boards should include the SoC dtsi. If other board DT writers don't do that or if they delete the fixed-link node from the CPU ports, that's not my problem and I don't really want to help them.
- seville_vsc9953 (arch/powerpc/boot/dts/fsl/t1040si-post.dtsi) on NXP T1040. Same thing, embedded switch, not my fault if the fixed-link disappears from the SoC dtsi.
- Colin Foster's SPI-controlled VSC7512 (still downstream). He has an Ethernet cable connecting the CPU port to a Beaglebone Black, so he has a phy-handle on the CPU port, so definitely not nothing. I believe his work hasn't made it to production in any case, so enforcing validation now shouldn't bother him too much if at all.
As for sja1105, there is DT validation that checks for the presence of all required properties in sja1105_parse_ports_node().
There is some DT validation in felix_parse_ports_node() too, but it doesn't check that all specifiers that phylink might use are there. I'd really like to add some validation before I gain any involuntary users, but all open-coded constructs I can come up with are clumsy. What would you suggest, if I explicitly don't want to rely on context-specific phylink interpretation of empty OF nodes, and rather error out?
Russell King (Oracle)
maintainerRe: [PATCH RFC net-next 5/5] net: dsa: always use phylink for CPU and DSA ports
Quoted 25 lines · Vladimir Oltean
Quoted 6 lines · Russell King (Oracle)
More importantly, we need your input on Ocelot, which you are listed as a maintainer for, and Ocelot is the only DSA driver that does stuff differently (due to the rate adapting PCS). It doesn't set
mac_capabilities, and thereforephylink_set_max_fixed_link()will not work here.Quoted 6 lines
Has Ocelot ever made use of this DSA feature where, when nothing is specified for a CPU or DSA port, we use an effective fixed-link setup with an interface mode that gives the highest speed? Or does this not apply to this DSA driver?
Thanks.
I'm fine with both the ocelot and sja1105 drivers.
The ocelot driver has 3 users:
-
felix_vsc9959(arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi) on NXP LS1028A, where the CPU ports have and have always had a fixed-link node in the SoC dtsi. LS1028A based boards should include the SoC dtsi. If other board DT writers don't do that or if they delete the fixed-link node from the CPU ports, that's not my problem and I don't really want to help them.
Quoted 3 lines
-
seville_vsc9953(arch/powerpc/boot/dts/fsl/t1040si-post.dtsi) on NXP T1040. Same thing, embedded switch, not my fault if the fixed-link disappears from the SoC dtsi.
Great, so I'll mark ocelot is safe.
Quoted 5 lines
- Colin Foster's SPI-controlled VSC7512 (still downstream). He has an Ethernet cable connecting the CPU port to a Beaglebone Black, so he has a phy-handle on the CPU port, so definitely not nothing. I believe his work hasn't made it to production in any case, so enforcing validation now shouldn't bother him too much if at all.
Ok, thanks.
Quoted 2 lines
As for sja1105, there is DT validation that checks for the presence of all required properties in
sja1105_parse_ports_node().
Looking at those, it requires all of:
- a phy mode to be specified (as determined by of_get_phy_mode())
- a phy-handle or of_phy_is_fixed_link() to return true
otherwise it errors out.
Quoted 2 lines
There is some DT validation in
felix_parse_ports_node()too, but it doesn't check that all specifiers that phylink might use are there.
Phylink (correction, fwnode_get_phy_node() which is not part of phylink anymore) will look for phy-handle, phy, or phy-device. This is I don't see that there's any incompatibility between what the driver is doing and what phylink does.
If there's a fixed-link property, then sja1105_parse_ports_node() is happy, and so will phylink. If there's a phy-handle, the same is true. If there's a "phy" or "phy-device" then sja1105_parse_ports_node() errors out. That's completely fine.
"phy" and "phy-device" are the backwards compatibility for DT - I believe one of them is the ePAPR specified property that we in Linux have decided to only fall back on if there's not our more modern "phy-handle" property.
It seems We have a lot of users of "phy" in DT today, so we can't drop that from generic code such as phylink, but I haven't found any users of "phy-device".
Quoted 5 lines
I'd really like to add some validation before I gain any involuntary users, but all open-coded constructs I can come up with are clumsy. What would you suggest, if I explicitly don't want to rely on context-specific phylink interpretation of empty OF nodes, and rather error out?
So I also don't see a problem - sja1105 rejects DTs that fail to describe a port using at least one of a phy-handle, a fixed-link, or a managed in-band link, and I don't think it needs to do further validation, certainly not for the phy describing properties that the kernel has chosen to deprecate for new implementations.
Signature · 2 lines
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/ FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!
Vladimir Oltean
maintainerRe: [PATCH RFC net-next 5/5] net: dsa: always use phylink for CPU and DSA ports
Quoted 1 line · Russell King (Oracle)
Great, so I'll mark ocelot is safe.
Yes, please.
Quoted 9 lines
Quoted 2 lines
As for sja1105, there is DT validation that checks for the presence of all required properties in
sja1105_parse_ports_node().Looking at those, it requires all of:
- a phy mode to be specified (as determined by
of_get_phy_mode())
- a phy-handle orof_phy_is_fixed_link()to return trueotherwise it errors out.
I know. The problem with this ad-hoc validation is that it doesn't cover the pure MLO_AN_INBAND:
managed = "in-band-status";
so it is more restrictive than it needs to be. Also it doesn't recognize the presence of an SFP bus in MLO_AN_PHY mode.
That is part 1 of my problem. I want to have validation that I'm providing phylink with all the right things it may need, but I don't want to make the driver code super clunky. By checking just the presence of either phy-handle or fixed-link I am rejecting valid phylink configurations. What I need is a validation function that is actually in sync with phylink, not just ad-hoc.
Quoted 28 lines
Quoted 2 lines
There is some DT validation in
felix_parse_ports_node()too, but it doesn't check that all specifiers that phylink might use are there.Phylink (correction,
fwnode_get_phy_node()which is not part of phylink anymore) will look for phy-handle, phy, or phy-device. This is I don't see that there's any incompatibility between what the driver is doing and what phylink does.If there's a fixed-link property, then
sja1105_parse_ports_node()is happy, and so will phylink. If there's a phy-handle, the same is true. If there's a "phy" or "phy-device" thensja1105_parse_ports_node()errors out. That's completely fine."phy" and "phy-device" are the backwards compatibility for DT - I believe one of them is the ePAPR specified property that we in Linux have decided to only fall back on if there's not our more modern "phy-handle" property.
It seems We have a lot of users of "phy" in DT today, so we can't drop that from generic code such as phylink, but I haven't found any users of "phy-device".
Quoted 5 lines
I'd really like to add some validation before I gain any involuntary users, but all open-coded constructs I can come up with are clumsy. What would you suggest, if I explicitly don't want to rely on context-specific phylink interpretation of empty OF nodes, and rather error out?
Quoted 5 lines
So I also don't see a problem - sja1105 rejects DTs that fail to describe a port using at least one of a phy-handle, a fixed-link, or a managed in-band link, and I don't think it needs to do further validation, certainly not for the phy describing properties that the kernel has chosen to deprecate for new implementations.
And this is part 2 of my problem, ocelot/felix doesn't have validation at all except for phy-mode, because if it were to simply copy the phy-handle/fixed-link either/or logic from sja1105, it would break some customer boards with SFP cages. But without that validation, I am exposing this driver to configurations I don't want it to support (CPU ports with empty OF nodes, i.o.w. what this patch set is about).
Quoted 11 lines · Russell King (Oracle)
A new revision of the series which incorporates changes that Marek suggested. Specifically, the changes are:
1. Patch 2 - use the
phylink_get_capsmethod in mv88e6xxx to get the default interface rather than re-usingport_max_speed_mode()2. Patch 4 - if no default interface is provided, use the supported interface mask to search for the first interface that gives the fastest speed.
3. Patch 5 - now also removes the
port_max_speed_mode()method
This was tested with bcm_sf2.c and b53_srab.b and did not cause regressions, however we do have a 'fixed-link' property for the CPU port (always have had one), so there was no regression expected.
See answers to your RFC v1 below.
Quoted 23 lines
drivers/net/dsa/b53/b53_common.c | 3 +- drivers/net/dsa/bcm_sf2.c | 3 +- drivers/net/dsa/hirschmann/hellcreek.c | 3 +- drivers/net/dsa/lantiq_gswip.c | 6 +- drivers/net/dsa/microchip/ksz_common.c | 3 +- drivers/net/dsa/mt7530.c | 3 +- drivers/net/dsa/mv88e6xxx/chip.c | 136 +++++++++++++++--------------- drivers/net/dsa/mv88e6xxx/chip.h | 6 +- drivers/net/dsa/mv88e6xxx/port.c | 32 ------- drivers/net/dsa/mv88e6xxx/port.h | 5 -- drivers/net/dsa/ocelot/felix.c | 3 +- drivers/net/dsa/qca/ar9331.c | 3 +- drivers/net/dsa/qca8k.c | 3 +- drivers/net/dsa/realtek/rtl8365mb.c | 3 +- drivers/net/dsa/sja1105/sja1105_main.c | 3 +- drivers/net/dsa/xrs700x/xrs700x.c | 3 +- drivers/net/phy/phylink.c | 150 ++++++++++++++++++++++++++++++--- include/linux/phylink.h | 5 ++ include/net/dsa.h | 3 +- net/dsa/port.c | 47 +++++++---- 20 files changed, 270 insertions(+), 153 deletions(-)
Quoted 84 lines
Quoted 83 lines · Russell King (Oracle)
Mostly the same as the previous RFC, except:
1) incldues the
phylink_validate_mask_caps()function
2) has Marek's idea of searching thesupported_interfacesbitmap for the fastest interface we can use
3) includes a final patch to add a print which will be useful to hear from people testing it.Some of the questions from the original RFC remain though, so I've included that text below. I'm guessing as they remain unanswered that no one has any opinions on them?
drivers/net/dsa/b53/b53_common.c | 3 +- drivers/net/dsa/bcm_sf2.c | 3 +- drivers/net/dsa/hirschmann/hellcreek.c | 3 +- drivers/net/dsa/lantiq_gswip.c | 6 +- drivers/net/dsa/microchip/ksz_common.c | 3 +- drivers/net/dsa/mt7530.c | 3 +- drivers/net/dsa/mv88e6xxx/chip.c | 53 ++++-------- drivers/net/dsa/ocelot/felix.c | 3 +- drivers/net/dsa/qca/ar9331.c | 3 +- drivers/net/dsa/qca8k.c | 3 +- drivers/net/dsa/realtek/rtl8365mb.c | 3 +- drivers/net/dsa/sja1105/sja1105_main.c | 3 +- drivers/net/dsa/xrs700x/xrs700x.c | 3 +- drivers/net/phy/phylink.c | 148 ++++++++++++++++++++++++++++++--- include/linux/phylink.h | 5 ++ include/net/dsa.h | 3 +- net/dsa/port.c | 47 +++++++---- 17 files changed, 215 insertions(+), 80 deletions(-)Quoted 51 lines · Russell King (Oracle)
Hi,
Currently, the core DSA code conditionally uses phylink for CPU and DSA ports depending on whether the firmware specifies a fixed-link or a PHY. If either of these are specified, then phylink is used for these ports, otherwise phylink is not, and we rely on the DSA drivers to "do the right thing". However, this detail is not mentioned in the DT binding, but Andrew has said that this behaviour has always something that DSA wants.
mv88e6xxx has had support for this for a long time with its "
SPEED_MAX" thing, which I recently reworked to make use of themac_capabilitiesin preparation to solving this more fully.This series is an experiment to solve this properly, and it does this in two steps.
The first step consists of the first two patches. Phylink needs to know the PHY interface mode that is being used so it can (a) pass the right mode into the MAC/PCS etc and (b) know the properties of the link and therefore which speeds can be supported across it.
In order to achieve this, the DSA
phylink_get_caps()method has an extra argument added to it so that DSA drivers can report the interface mode that they will be using for this port back to the core DSA code, thereby allowing phylink to be initialised with the correct interface mode.Note that this can only be used for CPU and DSA ports as "user" ports need a different behaviour - they rely on getting the interface mode from phylib, which will only happen if phylink is initialised with
PHY_INTERFACE_MODE_NA. Unfortunately, changing this behaviour is likely to cause widespread regressions.Obvious questions:
1. Shouldphylink_get_caps()be augmented in this way, or should it be a separate method?2. DSA has traditionally used "interface mode for the maximum supported speed on this port" where the interface mode is programmable (via its internal
port_max_speed_mode()method) but this is only present for a few of the sub-drivers. Is reporting the current interface mode correct where this method is not implemented?The second step is to introduce a function that allows phylink to be reconfigured after creation time to operate at max-speed fixed-link mode for the PHY interface mode, also using the MAC capabilities to determine the speed and duplex mode we should be using.
Obvious questions:
1. Should we be allowing half-duplex for this?
Except for testing, not sure I do see a point as it should not be a configuration being used at all?
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
2. If we do allow half-duplex, should we prefer fastest speed over duplex setting, or should we prefer fastest full-duplex speed over any half-duplex?
I would opt for fastest speed over duplex setting.
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
3. How do we sanely switch DSA from its current behaviour to always using phylink for these ports without breakage - this is the difficult one, because it's not obvious which drivers have been coded to either work around this quirk of the DSA implementation. For example, if we start forcing the link down before calling
dsa_port_phylink_create(), and we then fail to set max-fixed-link, then the CPU/DSA port is going to fail, and we're going to have lots of regressions.
Good question, we already have a legacy_pre_march2020 behavior for a piece of infrastructure code that is not so old, I doubt that we would want to add more of that type of quirk.
Signature · 1 line
Florian
Vladimir Oltean
maintainerHi Florian,
Quoted 11 lines · Florian Fainelli
Quoted 10 lines · Russell King (Oracle)
A new revision of the series which incorporates changes that Marek suggested. Specifically, the changes are:
1. Patch 2 - use the
phylink_get_capsmethod in mv88e6xxx to get the default interface rather than re-usingport_max_speed_mode()2. Patch 4 - if no default interface is provided, use the supported interface mask to search for the first interface that gives the fastest speed.
Quoted 5 lines
Quoted 1 line
3. Patch 5 - now also removes the
port_max_speed_mode()methodThis was tested with
bcm_sf2.cand b53_srab.b and did not cause regressions, however we do have a 'fixed-link' property for the CPU port (always have had one), so there was no regression expected.
What about arch/arm/boot/dts/bcm47189-tenda-ac9.dts?
Just to make sure I'm simply not seeing something, I compiled and then decompiled the dtb. We have:
ethernet@5000 {
reg = <0x5000 0x1000>;
phandle = <0x03>;
mdio {
#address-cells = <0x01>;
#size-cells = <0x00>;
switch@1e {
compatible = "brcm,bcm53125";
reg = <0x1e>;
status = "okay";
ports {
#address-cells = <0x01>;
#size-cells = <0x00>;
port@0 {
reg = <0x00>;
label = "wan";
};
port@1 {
reg = <0x01>;
label = "lan1";
};
port@2 {
reg = <0x02>;
label = "lan2";
};
port@3 {
reg = <0x03>;
label = "lan3";
};
port@4 {
reg = <0x04>;
label = "lan4";
};
port@5 {
reg = <0x05>;
label = "cpu";
ethernet = <0x03>; <- CPU port with no phy-handle, no fixed-link
};
};
};
};
};Quoted 14 lines · Vladimir Oltean
Hi Florian,
Quoted 11 lines · Florian Fainelli
Quoted 10 lines · Russell King (Oracle)
A new revision of the series which incorporates changes that Marek suggested. Specifically, the changes are:
1. Patch 2 - use the
phylink_get_capsmethod in mv88e6xxx to get the default interface rather than re-usingport_max_speed_mode()2. Patch 4 - if no default interface is provided, use the supported interface mask to search for the first interface that gives the fastest speed.
Quoted 7 lines
Quoted 5 lines
Quoted 1 line
3. Patch 5 - now also removes the
port_max_speed_mode()methodThis was tested with
bcm_sf2.cand b53_srab.b and did not cause regressions, however we do have a 'fixed-link' property for the CPU port (always have had one), so there was no regression expected.What about
arch/arm/boot/dts/bcm47189-tenda-ac9.dts?
You found one of the devices that I do not have access to and did not test, thanks. We do expect to run the port at 2GBits/sec on these devices however there is no "official" way to advertise that a port can run at 2Gbits/sec, as this is not even a "sanctioned" speed. I do have a similar device however, so let me run some more tests, we won't see a regression however since we do not use the NATP accelerator which would be the reason to run the port at 2Gbits/sec.
Signature · 1 line
Florian
Quoted 17 lines · Florian Fainelli
Quoted 16 lines · Vladimir Oltean
Hi Florian,
Quoted 13 lines · Florian Fainelli
Quoted 11 lines · Russell King (Oracle)
A new revision of the series which incorporates changes that Marek suggested. Specifically, the changes are:
1. Patch 2 - use the
phylink_get_capsmethod in mv88e6xxx to get the default interface rather than re-usingport_max_speed_mode()2. Patch 4 - if no default interface is provided, use the supported interface mask to search for the first interface that gives the fastest speed.
3. Patch 5 - now also removes the
port_max_speed_mode()method
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
This was tested with
bcm_sf2.cand b53_srab.b and did not cause regressions, however we do have a 'fixed-link' property for the CPU port (always have had one), so there was no regression expected.What about
arch/arm/boot/dts/bcm47189-tenda-ac9.dts?You found one of the devices that I do not have access to and did not test, thanks. We do expect to run the port at 2GBits/sec on these devices however there is no "official" way to advertise that a port can run at 2Gbits/sec, as this is not even a "sanctioned" speed. I do have a similar device however, so let me run some more tests, we won't see a regression however since we do not use the NATP accelerator which would be the reason to run the port at 2Gbits/sec.
I will try this change on some devices with the lantiq gswip driver at the weekend.
On the SoC supported by the lantiq gswip driver the switch is integrated in the SoC and there is a internal link with more than 1GBit/s connecting the switch to the rest of the system. I think it is also around 2GBit/s. We can not configure the interface speed or many other interface settings for the link between the switch and the CPU. How should the device tree ideally look for this setup?
Hauke
Russell King (Oracle)
maintainerQuoted 37 lines · Hauke Mehrtens
Quoted 25 lines · Florian Fainelli
Quoted 16 lines · Vladimir Oltean
Hi Florian,
Quoted 13 lines · Florian Fainelli
Quoted 11 lines · Russell King (Oracle)
A new revision of the series which incorporates changes that Marek suggested. Specifically, the changes are:
1. Patch 2 - use the
phylink_get_capsmethod in mv88e6xxx to get the default interface rather than re-usingport_max_speed_mode()2. Patch 4 - if no default interface is provided, use the supported interface mask to search for the first interface that gives the fastest speed.
3. Patch 5 - now also removes the
port_max_speed_mode()methodQuoted 7 lines
Quoted 5 lines
This was tested with
bcm_sf2.cand b53_srab.b and did not cause regressions,
however we do have a 'fixed-link' property for the CPU port (always have had
one), so there was no regression expected.What about
arch/arm/boot/dts/bcm47189-tenda-ac9.dts?Quoted 7 lines
You found one of the devices that I do not have access to and did not test, thanks. We do expect to run the port at 2GBits/sec on these devices however there is no "official" way to advertise that a port can run at 2Gbits/sec, as this is not even a "sanctioned" speed. I do have a similar device however, so let me run some more tests, we won't see a regression however since we do not use the NATP accelerator which would be the reason to run the port at 2Gbits/sec.
I will try this change on some devices with the lantiq gswip driver at the weekend.
Quoted 6 lines
On the SoC supported by the lantiq gswip driver the switch is integrated in the SoC and there is a internal link with more than 1GBit/s connecting the switch to the rest of the system. I think it is also around 2GBit/s. We can not configure the interface speed or many other interface settings for the link between the switch and the CPU. How should the device tree ideally look for this setup?
I think this falls into Andrew's "don't specify anything" category, which means that we should default to the maximum speed for the port - which is in this case quite clearly fixed at whatever the internal link actually is.
From the get_caps() function, the fastest speed apparently supported is 1Gbps. I'm guessing the CPU port is one of ports 2..5 on xrx200 and 1..5 on xrx300 - in which case, PHY_INTERFACE_MODE_INTERNAL is likely to be selected, which seems appropriate given what you've said above. (PHY_INTERFACE_MODE_INTERNAL will be the first interface type found that will give the highest speed as it permits any speed given in the mac_capabilities.)
Signature · 2 lines
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/ FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!
Kurt Kanzenbach
maintainerHi Russell,
Quoted 11 lines · Russell King
A new revision of the series which incorporates changes that Marek suggested. Specifically, the changes are:
1. Patch 2 - use the
phylink_get_capsmethod in mv88e6xxx to get the default interface rather than re-usingport_max_speed_mode()2. Patch 4 - if no default interface is provided, use the supported interface mask to search for the first interface that gives the fastest speed.
3. Patch 5 - now also removes the
port_max_speed_mode()method
Tested with hellcreek driver and no problems observed.
Thanks,
Kurt
Quoted 11 lines · Russell King (Oracle)
A new revision of the series which incorporates changes that Marek suggested. Specifically, the changes are:
1. Patch 2 - use the
phylink_get_capsmethod in mv88e6xxx to get the default interface rather than re-usingport_max_speed_mode()2. Patch 4 - if no default interface is provided, use the supported interface mask to search for the first interface that gives the fastest speed.
3. Patch 5 - now also removes the
port_max_speed_mode()method
Pulled in the patch set on top of net-next and tested on the D-Link DIR-685 with the RTL8366RB switch with no regressions, so:
The plan is to enhance the phylink handling in the RTL8366RB on top of Russell's patch in some time.
Yours,
Linus Walleij
Quoted 7 lines · Linus Walleij
Pulled in the patch set on top of net-next and tested on the D-Link DIR-685 with the RTL8366RB switch with no regressions, so:
Tested-by Linus Walleij <[email protected]>The plan is to enhance the phylink handling in the RTL8366RB on top of Russell's patch in some time.
I developed a patch like this and tested it, it works great and the DSA core now properly configures all the links (as expected).
I will send this out once Russell's patches are finalized and merged.
Yours,
Linus Walleij