Message ID | E1m5pwy-0003uX-Pf@rmk-PC.armlinux.org.uk (mailing list archive) |
---|---|
State | RFC |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | [RFC,net-next] net: phy: marvell10g: add downshift tunable support | expand |
Context | Check | Description |
---|---|---|
netdev/cover_letter | success | Link |
netdev/fixes_present | success | Link |
netdev/patch_count | success | Link |
netdev/tree_selection | success | Clearly marked for net-next |
netdev/subject_prefix | success | Link |
netdev/cc_maintainers | warning | 1 maintainers not CCed: linux@armlinux.org.uk |
netdev/source_inline | success | Was 0 now: 0 |
netdev/verify_signedoff | success | Link |
netdev/module_param | success | Was 0 now: 0 |
netdev/build_32bit | success | Errors and warnings before: 0 this patch: 0 |
netdev/kdoc | success | Errors and warnings before: 0 this patch: 0 |
netdev/verify_fixes | success | Link |
netdev/checkpatch | fail | ERROR: space required after that ',' (ctx:VxV) |
netdev/build_allmodconfig_warn | success | Errors and warnings before: 0 this patch: 0 |
netdev/header_inline | success | Link |
> +static int mv3310_set_downshift(struct phy_device *phydev, u8 ds) > +{ > + struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); > + u16 val; > + int err; > + > + /* Fails to downshift with v0.3.5.0 and earlier */ > + if (priv->firmware_ver < MV_VERSION(0,3,5,0)) > + return -EOPNOTSUPP; > + > + if (ds == DOWNSHIFT_DEV_DISABLE) > + return phy_clear_bits_mmd(phydev, MDIO_MMD_PCS, MV_PCS_DSC1, > + MV_PCS_DSC1_ENABLE); > + > + /* FIXME: The default is disabled, so should we disable? */ > + if (ds == DOWNSHIFT_DEV_DEFAULT_COUNT) > + ds = 2; Interesting question. It is a useful feature, so i would enable it by default. Is it possible to read the actual speed via some vendor register? The phy-core might then give a warning, but it is 50/50 since the link peer might perform the downshift. Andrew
On Tue, Jul 20, 2021 at 04:28:12PM +0200, Andrew Lunn wrote: > > +static int mv3310_set_downshift(struct phy_device *phydev, u8 ds) > > +{ > > + struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); > > + u16 val; > > + int err; > > + > > + /* Fails to downshift with v0.3.5.0 and earlier */ > > + if (priv->firmware_ver < MV_VERSION(0,3,5,0)) > > + return -EOPNOTSUPP; > > + > > + if (ds == DOWNSHIFT_DEV_DISABLE) > > + return phy_clear_bits_mmd(phydev, MDIO_MMD_PCS, MV_PCS_DSC1, > > + MV_PCS_DSC1_ENABLE); > > + > > + /* FIXME: The default is disabled, so should we disable? */ > > + if (ds == DOWNSHIFT_DEV_DEFAULT_COUNT) > > + ds = 2; > > Interesting question. > > It is a useful feature, so i would enable it by default. > > Is it possible to read the actual speed via some vendor register? The > phy-core might then give a warning, but it is 50/50 since the link > peer might perform the downshift. We already do read the actual negotiated speed anbd other parameters from the MV_PCS_CSSR1 register.
Hi Russell, On Tue, 20 Jul 2021 14:38:20 +0100 Russell King <rmk+kernel@armlinux.org.uk> wrote: > Add support for the downshift tunable for the Marvell 88x3310 PHY. > Downshift is only usable with firmware 0.3.5.0 and later. mv3310_{g,s}et_features are also used for 88E211x, but there is no such register in the documentation for these PHYs. (Also firmware versions on those are different, the newest is 8.3.0.0, but thats not important.) My solution would be to rename the current methods prefix to mv211x_ and and add new mv3310_{g,s}et_tunable methods. Marek
On Tue, Jul 20, 2021 at 05:04:24PM +0200, Marek Behún wrote: > Hi Russell, > > On Tue, 20 Jul 2021 14:38:20 +0100 > Russell King <rmk+kernel@armlinux.org.uk> wrote: > > > Add support for the downshift tunable for the Marvell 88x3310 PHY. > > Downshift is only usable with firmware 0.3.5.0 and later. > > mv3310_{g,s}et_features are also used for 88E211x, but there is no such > register in the documentation for these PHYs. (Also firmware versions on > those are different, the newest is 8.3.0.0, but thats not important.) > My solution would be to rename the current methods prefix to mv211x_ and > and add new mv3310_{g,s}et_tunable methods. There's more than just the tunables themselves - there's also config_init(). We already need to reject downshift when old firmware is running, as that fails to work correctly. So, we can just do that for 88E211x as well, adding a flag to struct mv3310_chip to indicate whether downshift is present. Sound sensible?
On Tue, 20 Jul 2021 18:14:01 +0100 "Russell King (Oracle)" <linux@armlinux.org.uk> wrote: > On Tue, Jul 20, 2021 at 05:04:24PM +0200, Marek Behún wrote: > > Hi Russell, > > > > On Tue, 20 Jul 2021 14:38:20 +0100 > > Russell King <rmk+kernel@armlinux.org.uk> wrote: > > > > > Add support for the downshift tunable for the Marvell 88x3310 PHY. > > > Downshift is only usable with firmware 0.3.5.0 and later. > > > > mv3310_{g,s}et_features are also used for 88E211x, but there is no > > such register in the documentation for these PHYs. (Also firmware > > versions on those are different, the newest is 8.3.0.0, but thats > > not important.) My solution would be to rename the current methods > > prefix to mv211x_ and and add new mv3310_{g,s}et_tunable methods. > > There's more than just the tunables themselves - there's also > config_init(). > > We already need to reject downshift when old firmware is running, > as that fails to work correctly. So, we can just do that for > 88E211x as well, adding a flag to struct mv3310_chip to indicate > whether downshift is present. Sound sensible? Hmm, maybe add the flag to struct mv3310_priv, instead of struct mv3310_chip, since the latter is static. And fill in the flag in mv3310_probe() function, depending on firmware version? BTW would you agree with a patch renaming the mv3310_ prefixes to mv10g_ for all functions that are generic to both mv3310_ and mv2110_? I was thinking about such a thing because it has become rather confusing. Marek
On Tue, Jul 20, 2021 at 07:32:23PM +0200, Marek Behún wrote: > On Tue, 20 Jul 2021 18:14:01 +0100 > "Russell King (Oracle)" <linux@armlinux.org.uk> wrote: > > > On Tue, Jul 20, 2021 at 05:04:24PM +0200, Marek Behún wrote: > > > Hi Russell, > > > > > > On Tue, 20 Jul 2021 14:38:20 +0100 > > > Russell King <rmk+kernel@armlinux.org.uk> wrote: > > > > > > > Add support for the downshift tunable for the Marvell 88x3310 PHY. > > > > Downshift is only usable with firmware 0.3.5.0 and later. > > > > > > mv3310_{g,s}et_features are also used for 88E211x, but there is no > > > such register in the documentation for these PHYs. (Also firmware > > > versions on those are different, the newest is 8.3.0.0, but thats > > > not important.) My solution would be to rename the current methods > > > prefix to mv211x_ and and add new mv3310_{g,s}et_tunable methods. > > > > There's more than just the tunables themselves - there's also > > config_init(). > > > > We already need to reject downshift when old firmware is running, > > as that fails to work correctly. So, we can just do that for > > 88E211x as well, adding a flag to struct mv3310_chip to indicate > > whether downshift is present. Sound sensible? > > Hmm, maybe add the flag to struct mv3310_priv, instead of struct > mv3310_chip, since the latter is static. And fill in the flag in > mv3310_probe() function, depending on firmware version? I was intending to leave the firmware version check where it was and just add a flag to say "this has downshift". The older firmwares on 3310 are basically buggy - they do downshift but only from 1G to 100M, they fail to go to 10M. > BTW would you agree with a patch renaming the mv3310_ prefixes to > mv10g_ for all functions that are generic to both mv3310_ and mv2110_? > I was thinking about such a thing because it has become rather > confusing. I've been thinking the same thing actually.
On Tue, 20 Jul 2021 18:39:41 +0100 "Russell King (Oracle)" <linux@armlinux.org.uk> wrote: > I was intending to leave the firmware version check where it was and > just add a flag to say "this has downshift". The older firmwares on > 3310 are basically buggy - they do downshift but only from 1G to 100M, > they fail to go to 10M. So we have two options * do the firmware version comparison at the position where the given feature is being configured * do the firmware version comparison in probe method and set specific flags for all features The second option is better if different PHYs have differnet system of versioning, but this can potentially lead to many different flags. I'll leave this decision to you. > > BTW would you agree with a patch renaming the mv3310_ prefixes to > > mv10g_ for all functions that are generic to both mv3310_ and > > mv2110_? > > I was thinking about such a thing because it has become rather > > confusing. > > I've been thinking the same thing actually. OK I will send a patch then once your downshift patch is applied. Marek
diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 0b7cae118ad7..0c9e7e1fab91 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -22,6 +22,7 @@ * If both the fiber and copper ports are connected, the first to gain * link takes priority and the other port is completely locked out. */ +#include <linux/bitfield.h> #include <linux/ctype.h> #include <linux/delay.h> #include <linux/hwmon.h> @@ -33,6 +34,8 @@ #define MV_PHY_ALASKA_NBT_QUIRK_MASK 0xfffffffe #define MV_PHY_ALASKA_NBT_QUIRK_REV (MARVELL_PHY_ID_88X3310 | 0xa) +#define MV_VERSION(a,b,c,d) ((a) << 24 | (b) << 16 | (c) << 8 | (d)) + enum { MV_PMA_FW_VER0 = 0xc011, MV_PMA_FW_VER1 = 0xc012, @@ -62,6 +65,15 @@ enum { MV_PCS_CSCR1_MDIX_MDIX = 0x0020, MV_PCS_CSCR1_MDIX_AUTO = 0x0060, + MV_PCS_DSC1 = 0x8003, + MV_PCS_DSC1_ENABLE = BIT(9), + MV_PCS_DSC1_10GBT = 0x01c0, + MV_PCS_DSC1_1GBR = 0x0038, + MV_PCS_DSC1_100BTX = 0x0007, + MV_PCS_DSC2 = 0x8004, + MV_PCS_DSC2_2P5G = 0xf000, + MV_PCS_DSC2_5G = 0x0f00, + MV_PCS_CSSR1 = 0x8008, MV_PCS_CSSR1_SPD1_MASK = 0xc000, MV_PCS_CSSR1_SPD1_SPD2 = 0xc000, @@ -330,6 +342,66 @@ static int mv3310_reset(struct phy_device *phydev, u32 unit) 5000, 100000, true); } +static int mv3310_get_downshift(struct phy_device *phydev, u8 *ds) +{ + struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); + int val; + + if (priv->firmware_ver < MV_VERSION(0,3,5,0)) + return -EOPNOTSUPP; + + val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_DSC1); + if (val < 0) + return val; + + if (val & MV_PCS_DSC1_ENABLE) + /* assume that all fields are the same */ + *ds = 1 + FIELD_GET(MV_PCS_DSC1_10GBT, (u16)val); + else + *ds = DOWNSHIFT_DEV_DISABLE; + + return 0; +} + +static int mv3310_set_downshift(struct phy_device *phydev, u8 ds) +{ + struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); + u16 val; + int err; + + /* Fails to downshift with v0.3.5.0 and earlier */ + if (priv->firmware_ver < MV_VERSION(0,3,5,0)) + return -EOPNOTSUPP; + + if (ds == DOWNSHIFT_DEV_DISABLE) + return phy_clear_bits_mmd(phydev, MDIO_MMD_PCS, MV_PCS_DSC1, + MV_PCS_DSC1_ENABLE); + + /* FIXME: The default is disabled, so should we disable? */ + if (ds == DOWNSHIFT_DEV_DEFAULT_COUNT) + ds = 2; + + if (ds > 8) + return -E2BIG; + + ds -= 1; + val = FIELD_PREP(MV_PCS_DSC2_2P5G, ds); + val |= FIELD_PREP(MV_PCS_DSC2_5G, ds); + err = phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_DSC2, + MV_PCS_DSC2_2P5G | MV_PCS_DSC2_5G, val); + if (err < 0) + return err; + + val = MV_PCS_DSC1_ENABLE; + val |= FIELD_PREP(MV_PCS_DSC1_10GBT, ds); + val |= FIELD_PREP(MV_PCS_DSC1_1GBR, ds); + val |= FIELD_PREP(MV_PCS_DSC1_100BTX, ds); + + return phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_DSC1, + MV_PCS_DSC1_ENABLE | MV_PCS_DSC1_10GBT | + MV_PCS_DSC1_1GBR | MV_PCS_DSC1_100BTX, val); +} + static int mv3310_get_edpd(struct phy_device *phydev, u16 *edpd) { int val; @@ -616,7 +688,16 @@ static int mv3310_config_init(struct phy_device *phydev) } /* Enable EDPD mode - saving 600mW */ - return mv3310_set_edpd(phydev, ETHTOOL_PHY_EDPD_DFLT_TX_MSECS); + err = mv3310_set_edpd(phydev, ETHTOOL_PHY_EDPD_DFLT_TX_MSECS); + if (err) + return err; + + /* Allow downshift */ + err = mv3310_set_downshift(phydev, DOWNSHIFT_DEV_DEFAULT_COUNT); + if (err && err != -EOPNOTSUPP) + return err; + + return 0; } static int mv3310_get_features(struct phy_device *phydev) @@ -886,6 +967,8 @@ static int mv3310_get_tunable(struct phy_device *phydev, struct ethtool_tunable *tuna, void *data) { switch (tuna->id) { + case ETHTOOL_PHY_DOWNSHIFT: + return mv3310_get_downshift(phydev, data); case ETHTOOL_PHY_EDPD: return mv3310_get_edpd(phydev, data); default: @@ -897,6 +980,8 @@ static int mv3310_set_tunable(struct phy_device *phydev, struct ethtool_tunable *tuna, const void *data) { switch (tuna->id) { + case ETHTOOL_PHY_DOWNSHIFT: + return mv3310_set_downshift(phydev, *(u8 *)data); case ETHTOOL_PHY_EDPD: return mv3310_set_edpd(phydev, *(u16 *)data); default:
Add support for the downshift tunable for the Marvell 88x3310 PHY. Downshift is only usable with firmware 0.3.5.0 and later. Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> --- It would be useful to have views on the "FIXME" comment in this patch please. Thanks. drivers/net/phy/marvell10g.c | 87 +++++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-)