aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2019-02-17 10:27:00 -0800
committerDavid S. Miller <davem@davemloft.net>2019-02-17 10:27:00 -0800
commit9e8ccd895704d61baebdefc164e524fb038d9697 (patch)
tree27ed80285ee6e8fbc0cbee4277be5a4ae6e7293d /drivers
parentMerge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next (diff)
parentnet: phy: marvell10g: check for newly set aneg (diff)
downloadlinux-9e8ccd895704d61baebdefc164e524fb038d9697.tar.gz
linux-9e8ccd895704d61baebdefc164e524fb038d9697.zip
Merge branch 'net-phy-add-and-use-genphy_c45_an_config_an'
Heiner Kallweit says: ==================== net: phy: add and use genphy_c45_an_config_an This series adds genphy_c45_an_config_an() and uses it in the marvell10g diver. In addition patch 4 aligns the aneg configuration with what is done in genphy_config_aneg(). v2: - in patch 2 changed function name to genphy_c45_an_config_aneg - in patch 3 add a comment regarding 1000BaseT vendor registers v3: - rebase patch 3 ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/phy/marvell10g.c31
-rw-r--r--drivers/net/phy/phy-c45.c44
2 files changed, 56 insertions, 19 deletions
diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
index 496805c0ddfe..b83eb19cf8bb 100644
--- a/drivers/net/phy/marvell10g.c
+++ b/drivers/net/phy/marvell10g.c
@@ -279,18 +279,15 @@ static int mv3310_config_aneg(struct phy_device *phydev)
return genphy_c45_an_disable_aneg(phydev);
}
- linkmode_and(phydev->advertising, phydev->advertising,
- phydev->supported);
-
- ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE,
- ADVERTISE_ALL | ADVERTISE_100BASE4 |
- ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM,
- linkmode_adv_to_mii_adv_t(phydev->advertising));
+ ret = genphy_c45_an_config_aneg(phydev);
if (ret < 0)
return ret;
if (ret > 0)
changed = true;
+ /* Clause 45 has no standardized support for 1000BaseT, therefore
+ * use vendor registers for this mode.
+ */
reg = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising);
ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MV_AN_CTRL1000,
ADVERTISE_1000FULL | ADVERTISE_1000HALF, reg);
@@ -299,19 +296,15 @@ static int mv3310_config_aneg(struct phy_device *phydev)
if (ret > 0)
changed = true;
- /* 10G control register */
- if (linkmode_test_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
- phydev->advertising))
- reg = MDIO_AN_10GBT_CTRL_ADV10G;
- else
- reg = 0;
+ if (!changed) {
+ /* Configure and restart aneg if it wasn't set before */
+ ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
+ if (ret < 0)
+ return ret;
- ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
- MDIO_AN_10GBT_CTRL_ADV10G, reg);
- if (ret < 0)
- return ret;
- if (ret > 0)
- changed = true;
+ if (!(ret & MDIO_AN_CTRL1_ENABLE))
+ changed = 1;
+ }
if (changed)
ret = genphy_c45_restart_aneg(phydev);
diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c
index 7af5fa81daf6..e17672bd180e 100644
--- a/drivers/net/phy/phy-c45.c
+++ b/drivers/net/phy/phy-c45.c
@@ -75,6 +75,50 @@ int genphy_c45_pma_setup_forced(struct phy_device *phydev)
EXPORT_SYMBOL_GPL(genphy_c45_pma_setup_forced);
/**
+ * genphy_c45_an_config_aneg - configure advertisement registers
+ * @phydev: target phy_device struct
+ *
+ * Configure advertisement registers based on modes set in phydev->advertising
+ *
+ * Returns negative errno code on failure, 0 if advertisement didn't change,
+ * or 1 if advertised modes changed.
+ */
+int genphy_c45_an_config_aneg(struct phy_device *phydev)
+{
+ int changed = 0, ret;
+ u32 adv;
+
+ linkmode_and(phydev->advertising, phydev->advertising,
+ phydev->supported);
+
+ adv = linkmode_adv_to_mii_adv_t(phydev->advertising);
+
+ ret = phy_modify_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE,
+ ADVERTISE_ALL | ADVERTISE_100BASE4 |
+ ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM,
+ adv);
+ if (ret < 0)
+ return ret;
+ if (ret > 0)
+ changed = 1;
+
+ adv = linkmode_adv_to_mii_10gbt_adv_t(phydev->advertising);
+
+ ret = phy_modify_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
+ MDIO_AN_10GBT_CTRL_ADV10G |
+ MDIO_AN_10GBT_CTRL_ADV5G |
+ MDIO_AN_10GBT_CTRL_ADV2_5G,
+ adv);
+ if (ret < 0)
+ return ret;
+ if (ret > 0)
+ changed = 1;
+
+ return changed;
+}
+EXPORT_SYMBOL_GPL(genphy_c45_an_config_aneg);
+
+/**
* genphy_c45_an_disable_aneg - disable auto-negotiation
* @phydev: target phy_device struct
*