diff options
author | Russell King <rmk+kernel@armlinux.org.uk> | 2020-01-04 00:41:35 +0000 |
---|---|---|
committer | Russell King (Oracle) <rmk+kernel@armlinux.org.uk> | 2025-04-04 14:40:03 +0100 |
commit | f702cdcaaa57a54ea63745d67c90945abc6e10eb (patch) | |
tree | 7b4836dd25ab97a34733cdee3d7bdb5073a00b2e | |
parent | 1bcf2fce41ccba2ba47df351f75648fecf34d4bc (diff) |
net: phy: marvell*: add support for hw resolved pause modes
Support reporting the hardware resolved pause enablement states via
phylib, overriding our software implementation.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
-rw-r--r-- | drivers/net/phy/marvell.c | 40 | ||||
-rw-r--r-- | drivers/net/phy/marvell10g.c | 6 |
2 files changed, 40 insertions, 6 deletions
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 44e1927de499..37e8247ee072 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -176,7 +176,11 @@ #define MII_M1011_PHY_STATUS_FULLDUPLEX 0x2000 #define MII_M1011_PHY_STATUS_RESOLVED 0x0800 #define MII_M1011_PHY_STATUS_LINK 0x0400 +#define MII_88E151X_PHY_STATUS_TX_PAUSE BIT(9) +#define MII_88E151X_PHY_STATUS_RX_PAUSE BIT(8) #define MII_M1011_PHY_STATUS_MDIX BIT(6) +#define MII_M1111_PHY_STATUS_TX_PAUSE BIT(3) +#define MII_M1111_PHY_STATUS_RX_PAUSE BIT(2) #define MII_88E3016_PHY_SPEC_CTRL 0x10 #define MII_88E3016_DISABLE_SCRAMBLER 0x0200 @@ -354,6 +358,8 @@ struct marvell_priv { u32 step; s8 pair; u8 vct_phase; + u16 tx_pause_mask; + u16 rx_pause_mask; }; static int marvell_read_page(struct phy_device *phydev) @@ -1664,6 +1670,7 @@ static void fiber_lpa_mod_linkmode_lpa_t(unsigned long *advertising, u32 lpa) static int marvell_read_status_page_an(struct phy_device *phydev, int fiber, int status) { + struct marvell_priv *priv = phydev->priv; int lpa; int err; @@ -1719,6 +1726,11 @@ static int marvell_read_status_page_an(struct phy_device *phydev, } } + phydev->resolved_tx_pause = !!(status & priv->tx_pause_mask); + phydev->resolved_rx_pause = !!(status & priv->rx_pause_mask); + phydev->resolved_pause_valid = !fiber && priv->tx_pause_mask && + priv->rx_pause_mask; + return 0; } @@ -1762,6 +1774,7 @@ static int marvell_read_status_page(struct phy_device *phydev, int page) phydev->speed = SPEED_UNKNOWN; phydev->duplex = DUPLEX_UNKNOWN; phydev->port = fiber ? PORT_FIBRE : PORT_TP; + phydev->resolved_pause_valid = false; if (fiber) { phydev->mdix = ETH_TP_MDI_INVALID; @@ -3568,7 +3581,8 @@ static int m88e1318_led_hw_control_get(struct phy_device *phydev, u8 index, return marvell_get_led_rules(index, rules, mode); } -static int marvell_probe(struct phy_device *phydev) +static int marvell_probe_pause(struct phy_device *phydev, u16 tx_pause_mask, + u16 rx_pause_mask) { struct marvell_priv *priv; @@ -3576,6 +3590,8 @@ static int marvell_probe(struct phy_device *phydev) if (!priv) return -ENOMEM; + priv->tx_pause_mask = tx_pause_mask; + priv->rx_pause_mask = rx_pause_mask; phydev->priv = priv; return marvell_hwmon_probe(phydev); @@ -3667,11 +3683,23 @@ static const struct sfp_upstream_ops m88e1510_sfp_ops = { .disconnect_phy = phy_sfp_disconnect_phy, }; +static int marvell_probe(struct phy_device *phydev) +{ + return marvell_probe_pause(phydev, 0, 0); +} + +static int m88e1111_probe(struct phy_device *phydev) +{ + return marvell_probe_pause(phydev, MII_M1111_PHY_STATUS_TX_PAUSE, + MII_M1111_PHY_STATUS_RX_PAUSE); +} + static int m88e1510_probe(struct phy_device *phydev) { int err; - err = marvell_probe(phydev); + err = marvell_probe_pause(phydev, MII_88E151X_PHY_STATUS_TX_PAUSE, + MII_88E151X_PHY_STATUS_RX_PAUSE); if (err) return err; @@ -3739,7 +3767,7 @@ static struct phy_driver marvell_drivers[] = { .name = "Marvell 88E1111", /* PHY_GBIT_FEATURES */ .flags = PHY_POLL_CABLE_TEST, - .probe = marvell_probe, + .probe = m88e1111_probe, .inband_caps = m88e1111_inband_caps, .config_inband = m88e1111_config_inband, .config_init = m88e1111gbe_config_init, @@ -3969,7 +3997,7 @@ static struct phy_driver marvell_drivers[] = { .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops), /* PHY_GBIT_FEATURES */ .flags = PHY_POLL_CABLE_TEST, - .probe = marvell_probe, + .probe = m88e1510_probe, .config_init = marvell_1011gbe_config_init, .config_aneg = m88e1510_config_aneg, .read_status = marvell_read_status, @@ -3998,7 +4026,7 @@ static struct phy_driver marvell_drivers[] = { .phy_id_mask = MARVELL_PHY_ID_MASK, .name = "Marvell 88E1545", .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops), - .probe = marvell_probe, + .probe = m88e1510_probe, /* PHY_GBIT_FEATURES */ .flags = PHY_POLL_CABLE_TEST, .config_init = marvell_1011gbe_config_init, @@ -4065,7 +4093,7 @@ static struct phy_driver marvell_drivers[] = { .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops), /* PHY_GBIT_FEATURES */ .flags = PHY_POLL_CABLE_TEST, - .probe = marvell_probe, + .probe = m88e1510_probe, .config_init = marvell_1011gbe_config_init, .config_aneg = m88e6390_config_aneg, .read_status = marvell_read_status, diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 3c6321635d37..22d2e9ec8fd6 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -83,6 +83,8 @@ enum { MV_PCS_CSSR1_SPD1_10 = 0x0000, MV_PCS_CSSR1_DUPLEX_FULL= BIT(13), MV_PCS_CSSR1_RESOLVED = BIT(11), + MV_PCS_CSSR1_TX_PAUSE = BIT(9), + MV_PCS_CSSR1_RX_PAUSE = BIT(8), MV_PCS_CSSR1_MDIX = BIT(6), MV_PCS_CSSR1_SPD2_MASK = 0x000c, MV_PCS_CSSR1_SPD2_5000 = 0x0008, @@ -1140,6 +1142,10 @@ static int mv3310_read_status_copper(struct phy_device *phydev) phydev->mdix = cssr1 & MV_PCS_CSSR1_MDIX ? ETH_TP_MDI_X : ETH_TP_MDI; + phydev->resolved_tx_pause = !!(cssr1 & MV_PCS_CSSR1_TX_PAUSE); + phydev->resolved_rx_pause = !!(cssr1 & MV_PCS_CSSR1_RX_PAUSE); + phydev->resolved_pause_valid = true; + if (val & MDIO_AN_STAT1_COMPLETE) { val = genphy_c45_read_lpa(phydev); if (val < 0) |