summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@armlinux.org.uk>2020-01-04 00:41:35 +0000
committerRussell King <rmk+kernel@armlinux.org.uk>2020-02-28 12:36:57 +0000
commitbf504f6f8146472fe5eb0323a1601fc6a4dee14e (patch)
tree835aabb168385807ea5e0f8fcfe1e4301cb3944c
parent6f6fefc0cc4a0913a651128d997d5b89ca3a52ce (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.c41
-rw-r--r--drivers/net/phy/marvell10g.c6
2 files changed, 45 insertions, 2 deletions
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 9a8badafea8a..dabf60641b93 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -152,6 +152,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
@@ -188,6 +192,8 @@ struct marvell_priv {
u64 stats[ARRAY_SIZE(marvell_hw_stats)];
char *hwmon_name;
struct device *hwmon_dev;
+ u16 tx_pause_mask;
+ u16 rx_pause_mask;
};
static int marvell_read_page(struct phy_device *phydev)
@@ -1275,6 +1281,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;
@@ -1328,6 +1335,11 @@ static int marvell_read_status_page_an(struct phy_device *phydev,
break;
}
+ 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;
}
@@ -1370,6 +1382,7 @@ static int marvell_read_status_page(struct phy_device *phydev, int page)
phydev->asym_pause = 0;
phydev->speed = SPEED_UNKNOWN;
phydev->duplex = DUPLEX_UNKNOWN;
+ phydev->resolved_pause_valid = false;
if (phydev->autoneg == AUTONEG_ENABLE)
err = marvell_read_status_page_an(phydev, fiber, status);
@@ -2130,6 +2143,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;
@@ -2141,11 +2171,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;
@@ -2208,7 +2245,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 = &marvell_config_aneg,
.read_status = &marvell_read_status,
diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
index 88720fa5c611..c3c901128ef2 100644
--- a/drivers/net/phy/marvell10g.c
+++ b/drivers/net/phy/marvell10g.c
@@ -48,6 +48,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,
@@ -537,6 +539,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)