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> | 2021-06-07 11:26:47 +0100 |
commit | 75da6b555f415ba92e3df85509b4b5e788155383 (patch) | |
tree | 6ec1d93877a615c4895657d642ab172fb4cbb0ae | |
parent | b169cb408813b15e20a6db7b4060ee68b45db729 (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 | 41 | ||||
-rw-r--r-- | drivers/net/phy/marvell10g.c | 6 |
2 files changed, 45 insertions, 2 deletions
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 8018ddf7f316..5701b2f855ec 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -158,6 +158,10 @@ #define MII_M1011_PHY_STATUS_FULLDUPLEX 0x2000 #define MII_M1011_PHY_STATUS_RESOLVED 0x0800 #define MII_M1011_PHY_STATUS_LINK 0x0400 +#define MII_M1111_PHY_STATUS_TX_PAUSE 0x0008 +#define MII_M1111_PHY_STATUS_RX_PAUSE 0x0004 +#define MII_88E151X_PHY_STATUS_TX_PAUSE 0x0200 +#define MII_88E151X_PHY_STATUS_RX_PAUSE 0x0100 #define MII_88E3016_PHY_SPEC_CTRL 0x10 #define MII_88E3016_DISABLE_SCRAMBLER 0x0200 @@ -283,6 +287,8 @@ struct marvell_priv { u32 last; u32 step; s8 pair; + u16 tx_pause_mask; + u16 rx_pause_mask; }; static int marvell_read_page(struct phy_device *phydev) @@ -1458,6 +1464,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; @@ -1513,6 +1520,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; } @@ -1556,6 +1568,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 (phydev->autoneg == AUTONEG_ENABLE) err = marvell_read_status_page_an(phydev, fiber, status); @@ -2674,6 +2687,23 @@ static int marvell_probe(struct phy_device *phydev) return 0; } +static int marvell_probe_pause(struct phy_device *phydev, u16 tx_pause_mask, + u16 rx_pause_mask) +{ + struct marvell_priv *priv; + int err; + + err = marvell_probe(phydev); + if (err) + return err; + + priv = phydev->priv; + priv->tx_pause_mask = tx_pause_mask; + priv->rx_pause_mask = rx_pause_mask; + + return 0; +} + static int m88e1121_probe(struct phy_device *phydev) { int err; @@ -2685,11 +2715,18 @@ static int m88e1121_probe(struct phy_device *phydev) return m88e1121_hwmon_probe(phydev); } +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; @@ -2751,7 +2788,7 @@ static struct phy_driver marvell_drivers[] = { .phy_id_mask = MARVELL_PHY_ID_MASK, .name = "Marvell 88E1111", /* PHY_GBIT_FEATURES */ - .probe = marvell_probe, + .probe = m88e1111_probe, .config_init = m88e1111_config_init, .config_aneg = m88e1111_config_aneg, .read_status = marvell_read_status, diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 384962cd8df1..528367c71621 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -73,6 +73,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, @@ -825,6 +827,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) |